web-console 2.1.3 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.markdown +45 -0
- data/README.markdown +26 -6
- data/Rakefile +37 -0
- data/lib/web_console/extensions.rb +2 -1
- data/lib/web_console/integration/cruby.rb +2 -1
- data/lib/web_console/integration/rubinius.rb +2 -1
- data/lib/web_console/railtie.rb +19 -1
- data/lib/web_console/session.rb +4 -3
- data/lib/web_console/templates/_inner_console_markup.html.erb +8 -3
- data/lib/web_console/templates/console.js.erb +169 -46
- data/lib/web_console/templates/error_page.js.erb +2 -15
- data/lib/web_console/templates/main.js.erb +1 -24
- data/lib/web_console/templates/style.css.erb +22 -9
- data/lib/web_console/tracer.rb +11 -0
- data/lib/web_console/version.rb +1 -1
- metadata +5 -155
- data/test/dummy/README.rdoc +0 -28
- data/test/dummy/Rakefile +0 -6
- data/test/dummy/app/assets/javascripts/application.js +0 -13
- data/test/dummy/app/assets/stylesheets/application.css +0 -13
- data/test/dummy/app/controllers/application_controller.rb +0 -5
- data/test/dummy/app/controllers/controller_helper_test_controller.rb +0 -7
- data/test/dummy/app/controllers/exception_test_controller.rb +0 -15
- data/test/dummy/app/controllers/helper_error_controller.rb +0 -4
- data/test/dummy/app/controllers/helper_test_controller.rb +0 -5
- data/test/dummy/app/controllers/tests_controller.rb +0 -16
- data/test/dummy/app/helpers/application_helper.rb +0 -2
- data/test/dummy/app/views/controller_helper_test/index.html.erb +0 -1
- data/test/dummy/app/views/exception_test/xhr.html.erb +0 -1
- data/test/dummy/app/views/helper_error/index.html.erb +0 -2
- data/test/dummy/app/views/helper_test/index.html.erb +0 -220
- data/test/dummy/app/views/layouts/application.html.erb +0 -16
- data/test/dummy/bin/bundle +0 -3
- data/test/dummy/bin/rails +0 -4
- data/test/dummy/bin/rake +0 -4
- data/test/dummy/config.ru +0 -4
- data/test/dummy/config/application.rb +0 -19
- data/test/dummy/config/boot.rb +0 -5
- data/test/dummy/config/database.yml +0 -25
- data/test/dummy/config/environment.rb +0 -5
- data/test/dummy/config/environments/development.rb +0 -29
- data/test/dummy/config/environments/production.rb +0 -80
- data/test/dummy/config/environments/test.rb +0 -34
- data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
- data/test/dummy/config/initializers/filter_parameter_logging.rb +0 -4
- data/test/dummy/config/initializers/inflections.rb +0 -16
- data/test/dummy/config/initializers/mime_types.rb +0 -5
- data/test/dummy/config/initializers/secret_token.rb +0 -12
- data/test/dummy/config/initializers/session_store.rb +0 -3
- data/test/dummy/config/initializers/wrap_parameters.rb +0 -14
- data/test/dummy/config/locales/en.yml +0 -23
- data/test/dummy/config/routes.rb +0 -15
- data/test/dummy/db/schema.rb +0 -16
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/test.log +0 -808
- data/test/dummy/public/404.html +0 -58
- data/test/dummy/public/422.html +0 -58
- data/test/dummy/public/500.html +0 -57
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/0c9b99b1b975b36a5b686845ae729db3 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/12e9f58adcf819cf65fd68b6859a438f +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/1fd6abead3df36a4e4a2cb042a551b39 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/33b5eb81b5aaaa1e6dd5dcb6517792b4 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/3e460b2e021085f88b5597b38d194932 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/52f04b2ea6e461f4661b6d0be393fa94 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/688c344c2919f882338f06c5daaea209 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/7f079298e19bbef40a5d6a37dc03033a +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/91aa709f89e465f58056fabe5f75eef4 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/95f4e4e5217aec9f71b2c1a65a9a9231 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/9c41be9b6625756fbb6d05b7665dd911 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/a95f64d41fcf8244b8f5b84a55f07822 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/c5e6bf1efd5929bee63e28ad7c9f6f83 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/d863259e9eeca657a1624135cfe24446 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/e1d2fc4601b6423ec8a42415ee05dd14 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/e82616536a759c2e87d703adc77d65da +0 -0
- data/test/support/scenarios/bad_custom_error_scenario.rb +0 -17
- data/test/support/scenarios/basic_nested_scenario.rb +0 -15
- data/test/support/scenarios/custom_error_scenario.rb +0 -11
- data/test/support/scenarios/eval_nested_scenario.rb +0 -15
- data/test/support/scenarios/flat_scenario.rb +0 -9
- data/test/support/scenarios/reraised_scenario.rb +0 -21
- data/test/test_helper.rb +0 -78
- data/test/web_console/evaluator_test.rb +0 -73
- data/test/web_console/extensions_test.rb +0 -28
- data/test/web_console/helper_test.rb +0 -76
- data/test/web_console/integration_test.rb +0 -47
- data/test/web_console/middleware_test.rb +0 -116
- data/test/web_console/railtie_test.rb +0 -99
- data/test/web_console/request_test.rb +0 -82
- data/test/web_console/session_test.rb +0 -59
- data/test/web_console/whiny_request_test.rb +0 -33
- data/test/web_console/whitelist_test.rb +0 -43
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bde2832a1ef7a0ace010d61011afb4c74a116a93
|
4
|
+
data.tar.gz: c0e5de96dab453f1a3e233d969bf5ada72ba848a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eb74d0994835ccc223df24cb3a5ee1e034ca2456580f99962724864994438f04a14c67aa05f9425263f1c36773623969abdc7bca5a2b255535e90449b6394ac3
|
7
|
+
data.tar.gz: 31f90bb5c32ed53a95f43cb1a0f25cf89765847c92010255a9df5c0235423203711be37e09eda9af4f435616772d247502b682a2ef367f5409cbbbcc23cca963
|
data/CHANGELOG.markdown
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# CHANGELOG
|
2
|
+
|
3
|
+
## master (unreleased)
|
4
|
+
|
5
|
+
## 2.2.0
|
6
|
+
|
7
|
+
* [#140](https://github.com/rails/web-console/pull/140) Add the ability to close the console on each page ([@sh19910711])
|
8
|
+
* [#135](https://github.com/rails/web-console/pull/135) Run the console only in development mode and raise warning in tests ([@frenesim])
|
9
|
+
|
10
|
+
## 2.1.3
|
11
|
+
|
12
|
+
* Fix remote code execution vulnerability in Web Console. CVE-2015-3224.
|
13
|
+
* [#123](https://github.com/rails/web-console/pull/123) Replace deprecated `alias_method_chain` with `alias_method` ([@jonatack])
|
14
|
+
|
15
|
+
## 2.1.2
|
16
|
+
|
17
|
+
* [#115](https://github.com/rails/web-console/pull/115) Show proper binding when raising an error in a template ([@gsamokovarov])
|
18
|
+
* [#114](https://github.com/rails/web-console/pull/114) Fix templates non rendering, because of missing template suffix ([@gsamokovarov])
|
19
|
+
|
20
|
+
## 2.1.1
|
21
|
+
|
22
|
+
* [#112](https://github.com/rails/web-console/pull/112) Always allow application/x-www-form-urlencoded content type ([@gsamokovarov])
|
23
|
+
|
24
|
+
## 2.1.0
|
25
|
+
|
26
|
+
* [#109](https://github.com/rails/web-console/pull/109) Revamp unavailable session response message ([@gsamokovarov])
|
27
|
+
* [#107](https://github.com/rails/web-console/pull/107) Fix pasting regression for all browsers ([@parterburn])
|
28
|
+
* [#105](https://github.com/rails/web-console/pull/105) Lock scroll bottom on console window resize ([@noahpatterson])
|
29
|
+
* [#104](https://github.com/rails/web-console/pull/104) Always whitelist localhost and inform users why no console is displayed ([@gsamokovarov])
|
30
|
+
* [#100](https://github.com/rails/web-console/pull/100) Accept text/plain as acceptable content type for Puma ([@gsamokovarov])
|
31
|
+
* [#98](https://github.com/rails/web-console/pull/98) Add arbitrary big z-index to the console ([@bglbruno])
|
32
|
+
* [#88](https://github.com/rails/web-console/pull/88) Spelling fixes ([@jeffnv])
|
33
|
+
* [#86](https://github.com/rails/web-console/pull/86) Disable autofocus when initializing the console ([@ryandao])
|
34
|
+
* [#84](https://github.com/rails/web-console/pull/84) Allow Rails 5 as dependency in gemspec ([@jonatack])
|
35
|
+
* [#69](https://github.com/rails/web-console/pull/69) Introduce middleware for request dispatch and console rendering ([@gsamokovarov])
|
36
|
+
|
37
|
+
[@jonatack]: https://github.com/jonatack
|
38
|
+
[@ryandao]: https://github.com/ryandao
|
39
|
+
[@jeffnv]: https://github.com/jeffnv
|
40
|
+
[@gsamokovarov]: https://github.com/gsamokovarov
|
41
|
+
[@bglbruno]: https://github.com/bglbruno
|
42
|
+
[@noahpatterson]: https://github.com/noahpatterson
|
43
|
+
[@parterburn]: https://github.com/parterburn
|
44
|
+
[@sh19910711]: https://github.com/sh19910711
|
45
|
+
[@frenesim]: https://github.com/frenesim
|
data/README.markdown
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
<p align=right>
|
2
2
|
Documentation for:
|
3
3
|
<a href=https://github.com/rails/web-console/tree/v2.0.0>v2.0.0</a>
|
4
|
+
<a href=https://github.com/rails/web-console/tree/v2.1.0>v2.1.0</a>
|
5
|
+
<a href=https://github.com/rails/web-console/tree/v2.1.1>v2.1.1</a>
|
6
|
+
<a href=https://github.com/rails/web-console/tree/v2.1.2>v2.1.2</a>
|
7
|
+
<a href=https://github.com/rails/web-console/tree/v2.1.3>v2.1.3</a>
|
4
8
|
</p>
|
5
9
|
|
6
10
|
# Web Console [![Build Status](https://travis-ci.org/rails/web-console.svg?branch=master)](https://travis-ci.org/rails/web-console)
|
@@ -119,7 +123,7 @@ end
|
|
119
123
|
If you want to whitelist the whole private network, you can do:
|
120
124
|
|
121
125
|
```ruby
|
122
|
-
|
126
|
+
Rails.application.configure do
|
123
127
|
config.web_console.whitelisted_ips = '192.168.0.0/16'
|
124
128
|
end
|
125
129
|
```
|
@@ -138,19 +142,19 @@ messages like the following is printed in the server logs:
|
|
138
142
|
If you don't wanna see this message anymore, set this option to `false`:
|
139
143
|
|
140
144
|
```ruby
|
141
|
-
|
145
|
+
Rails.application.configure do
|
142
146
|
config.web_console.whiny_requests = false
|
143
147
|
end
|
144
148
|
```
|
145
149
|
|
146
|
-
### config.web_console.
|
150
|
+
### config.web_console.template_paths
|
147
151
|
|
148
152
|
If you wanna style the console yourself, you can place `style.css` at a
|
149
|
-
directory pointed by `config.web_console.
|
153
|
+
directory pointed by `config.web_console.template_paths`:
|
150
154
|
|
151
155
|
```ruby
|
152
|
-
|
153
|
-
config.web_console.
|
156
|
+
Rails.application.configure do
|
157
|
+
config.web_console.template_paths = 'app/views/web_console'
|
154
158
|
end
|
155
159
|
```
|
156
160
|
|
@@ -181,6 +185,22 @@ server requests only out of one process.
|
|
181
185
|
The interactive console executes Ruby code. Invoking `instance_variables` and
|
182
186
|
`local_variables` will give you what you want.
|
183
187
|
|
188
|
+
### Why does console only appear on error pages but not when I call it?
|
189
|
+
|
190
|
+
This can be happening if you are using `Rack::Deflater`. Be sure that
|
191
|
+
`WebConsole::Middleware` is used after `Rack::Deflater`. The easiest way to do
|
192
|
+
this is to insert `Rack::Deflater` as early as possible
|
193
|
+
|
194
|
+
```ruby
|
195
|
+
Rails.application.configure do
|
196
|
+
config.middleware.insert(0, Rack::Deflater)
|
197
|
+
end
|
198
|
+
```
|
199
|
+
|
200
|
+
### Why I'm getting an undefined method `web_console`?
|
201
|
+
|
202
|
+
Make sure you configuration lives in `config/environments/development.rb`.
|
203
|
+
|
184
204
|
## Credits
|
185
205
|
|
186
206
|
* Shoutout to [Charlie Somerville] for [better_errors] and [this] code.
|
data/Rakefile
CHANGED
@@ -6,6 +6,8 @@ end
|
|
6
6
|
|
7
7
|
require 'socket'
|
8
8
|
require 'rake/testtask'
|
9
|
+
require 'tmpdir'
|
10
|
+
require 'securerandom'
|
9
11
|
|
10
12
|
EXPANDED_CWD = File.expand_path(File.dirname(__FILE__))
|
11
13
|
|
@@ -16,6 +18,41 @@ Rake::TestTask.new(:test) do |t|
|
|
16
18
|
t.verbose = false
|
17
19
|
end
|
18
20
|
|
21
|
+
namespace :test do
|
22
|
+
desc "Run tests for templates"
|
23
|
+
task :templates => "templates:all"
|
24
|
+
|
25
|
+
namespace :templates do
|
26
|
+
task :all => [:daemonize, :npm, :rackup, :mocha, :kill]
|
27
|
+
task :serve => [:npm, :rackup]
|
28
|
+
|
29
|
+
work_dir = Pathname(__FILE__).dirname.join("test/templates")
|
30
|
+
pid_file = Pathname(Dir.tmpdir).join("web_console.#{SecureRandom.uuid}.pid")
|
31
|
+
server_port = 29292
|
32
|
+
rackup_opts = "-p #{server_port}"
|
33
|
+
|
34
|
+
task :daemonize do
|
35
|
+
rackup_opts += " -D -P #{pid_file}"
|
36
|
+
end
|
37
|
+
|
38
|
+
task :npm do
|
39
|
+
Dir.chdir(work_dir) { system "npm install --silent" }
|
40
|
+
end
|
41
|
+
|
42
|
+
task :rackup do
|
43
|
+
Dir.chdir(work_dir) { system "bundle exec rackup #{rackup_opts}" }
|
44
|
+
end
|
45
|
+
|
46
|
+
task :mocha do
|
47
|
+
Dir.chdir(work_dir) { system "$(npm bin)/mocha-phantomjs http://localhost:#{server_port}/html/spec_runner.html" }
|
48
|
+
end
|
49
|
+
|
50
|
+
task :kill do
|
51
|
+
system "kill #{File.read pid_file}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
19
56
|
Bundler::GemHelper.install_tasks
|
20
57
|
|
21
58
|
task default: :test
|
@@ -15,5 +15,6 @@ ActionDispatch::DebugExceptions.class_eval do
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
|
18
|
+
alias_method :render_exception_without_web_console, :render_exception
|
19
|
+
alias_method :render_exception, :render_exception_with_web_console
|
19
20
|
end
|
@@ -34,6 +34,7 @@ class Exception
|
|
34
34
|
set_backtrace_without_binding_of_caller(*args)
|
35
35
|
end
|
36
36
|
|
37
|
-
|
37
|
+
alias_method :set_backtrace_without_binding_of_caller, :set_backtrace
|
38
|
+
alias_method :set_backtrace, :set_backtrace_with_binding_of_caller
|
38
39
|
end
|
39
40
|
end
|
@@ -62,5 +62,6 @@ end
|
|
62
62
|
raise_exception_without_current_bindings(exc)
|
63
63
|
end
|
64
64
|
|
65
|
-
|
65
|
+
alias_method :raise_exception_without_current_bindings, :raise_exception
|
66
|
+
alias_method :raise_exception, :raise_exception_with_current_bindings
|
66
67
|
end
|
data/lib/web_console/railtie.rb
CHANGED
@@ -17,11 +17,29 @@ module WebConsole
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
+
initializer 'web_console.development_only' do
|
21
|
+
unless (config.web_console.development_only == false) || Rails.env.development?
|
22
|
+
abort <<-END.strip_heredoc
|
23
|
+
Web Console is activated in the #{Rails.env} environment, which is
|
24
|
+
usually a mistake. To ensure it's only activated in development
|
25
|
+
mode, move it to the development group of your Gemfile:
|
26
|
+
|
27
|
+
gem 'web-console', group: :development
|
28
|
+
|
29
|
+
If you still want to run it the #{Rails.env} environment (and know
|
30
|
+
what you are doing), put this in your Rails application
|
31
|
+
configuration:
|
32
|
+
|
33
|
+
config.web_console.development_only = false
|
34
|
+
END
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
20
38
|
initializer 'web_console.insert_middleware' do |app|
|
21
39
|
app.middleware.insert_before ActionDispatch::DebugExceptions, Middleware
|
22
40
|
end
|
23
41
|
|
24
|
-
initializer 'web_console.
|
42
|
+
initializer 'web_console.template_paths' do
|
25
43
|
if template_paths = config.web_console.template_paths
|
26
44
|
Template.template_paths.unshift(*Array(template_paths))
|
27
45
|
end
|
data/lib/web_console/session.rb
CHANGED
@@ -9,7 +9,8 @@ module WebConsole
|
|
9
9
|
# error pages only, as currently, this is the only client that needs to do
|
10
10
|
# that.
|
11
11
|
class Session
|
12
|
-
|
12
|
+
cattr_reader :inmemory_storage
|
13
|
+
@@inmemory_storage = {}
|
13
14
|
|
14
15
|
class << self
|
15
16
|
# Finds a persisted session in memory by its id.
|
@@ -17,7 +18,7 @@ module WebConsole
|
|
17
18
|
# Returns a persisted session if found in memory.
|
18
19
|
# Raises NotFound error unless found in memory.
|
19
20
|
def find(id)
|
20
|
-
|
21
|
+
inmemory_storage[id]
|
21
22
|
end
|
22
23
|
|
23
24
|
# Create a Session from an exception.
|
@@ -59,7 +60,7 @@ module WebConsole
|
|
59
60
|
private
|
60
61
|
|
61
62
|
def store_into_memory
|
62
|
-
|
63
|
+
inmemory_storage[id] = self
|
63
64
|
end
|
64
65
|
end
|
65
66
|
end
|
@@ -1,3 +1,8 @@
|
|
1
|
-
<div
|
2
|
-
<div class='console-
|
3
|
-
<
|
1
|
+
<div class='resizer layer'></div>
|
2
|
+
<div class='console-outer layer'>
|
3
|
+
<div class='console-actions'>
|
4
|
+
<div class='close-button button' title='close'>x</div>
|
5
|
+
</div>
|
6
|
+
<div class='console-inner'></div>
|
7
|
+
</div>
|
8
|
+
<input class='clipboard' type='text'>
|
@@ -1,40 +1,3 @@
|
|
1
|
-
// DOM helpers
|
2
|
-
function hasClass(el, className) {
|
3
|
-
var regex = new RegExp('(?:^|\\s)' + className + '(?!\\S)', 'g');
|
4
|
-
return el.className.match(regex);
|
5
|
-
}
|
6
|
-
|
7
|
-
function addClass(el, className) {
|
8
|
-
el.className += " " + className;
|
9
|
-
}
|
10
|
-
|
11
|
-
function removeClass(el, className) {
|
12
|
-
var regex = new RegExp('(?:^|\\s)' + className + '(?!\\S)', 'g');
|
13
|
-
el.className = el.className.replace(regex, '');
|
14
|
-
}
|
15
|
-
|
16
|
-
function removeAllChildren(el) {
|
17
|
-
while (el.firstChild) {
|
18
|
-
el.removeChild(el.firstChild);
|
19
|
-
}
|
20
|
-
}
|
21
|
-
|
22
|
-
function escapeHTML(html) {
|
23
|
-
return html
|
24
|
-
.replace(/&/g, '&')
|
25
|
-
.replace(/</g, '<')
|
26
|
-
.replace(/>/g, '>')
|
27
|
-
.replace(/"/g, '"')
|
28
|
-
.replace(/'/g, ''')
|
29
|
-
.replace(/`/g, '`');
|
30
|
-
}
|
31
|
-
|
32
|
-
// Add CSS styles dynamically. This probably doesnt work for IE <8.
|
33
|
-
var style = document.createElement('style');
|
34
|
-
style.type = 'text/css';
|
35
|
-
style.innerHTML = <%= render_inlined_string 'style.css' %>;
|
36
|
-
document.getElementsByTagName('head')[0].appendChild(style);
|
37
|
-
|
38
1
|
/**
|
39
2
|
* Constructor for command storage.
|
40
3
|
* It uses localStorage if available. Otherwise fallback to normal JS array.
|
@@ -84,6 +47,10 @@ function CommandStorage() {
|
|
84
47
|
// HTML strings for dynamic elements.
|
85
48
|
var consoleInnerHtml = <%= render_inlined_string '_inner_console_markup.html' %>;
|
86
49
|
var promptBoxHtml = <%= render_inlined_string '_prompt_box_markup.html' %>;
|
50
|
+
// CSS
|
51
|
+
var consoleStyleCss = <%= render_inlined_string 'style.css' %>;
|
52
|
+
// Insert a style element with the unique ID
|
53
|
+
var styleElementId = 'sr02459pvbvrmhco';
|
87
54
|
|
88
55
|
// REPLConsole Constructor
|
89
56
|
function REPLConsole(config) {
|
@@ -122,17 +89,25 @@ REPLConsole.prototype.install = function(container) {
|
|
122
89
|
// Render the console.
|
123
90
|
container.innerHTML = consoleInnerHtml;
|
124
91
|
|
92
|
+
var consoleOuter = findChild(container, 'console-outer');
|
93
|
+
var consoleActions = findChild(consoleOuter, 'console-actions');
|
94
|
+
|
95
|
+
addClass(container, 'console');
|
96
|
+
addClass(container.getElementsByClassName('layer'), 'pos-absolute border-box');
|
97
|
+
addClass(container.getElementsByClassName('button'), 'border-box');
|
98
|
+
addClass(consoleActions, 'pos-fixed pos-right');
|
99
|
+
|
125
100
|
// Make the console resizable.
|
126
|
-
|
101
|
+
function resizeContainer(ev) {
|
127
102
|
var startY = ev.clientY;
|
128
103
|
var startHeight = parseInt(document.defaultView.getComputedStyle(container).height, 10);
|
129
|
-
var
|
130
|
-
var
|
131
|
-
var innerClientHeightStart = consoleInner.clientHeight;
|
104
|
+
var scrollTopStart = consoleOuter.scrollTop;
|
105
|
+
var clientHeightStart = consoleOuter.clientHeight;
|
132
106
|
|
133
107
|
var doDrag = function(e) {
|
134
108
|
container.style.height = (startHeight + startY - e.clientY) + 'px';
|
135
|
-
|
109
|
+
consoleOuter.scrollTop = scrollTopStart + (clientHeightStart - consoleOuter.clientHeight);
|
110
|
+
shiftConsoleActions();
|
136
111
|
};
|
137
112
|
|
138
113
|
var stopDrag = function(e) {
|
@@ -142,12 +117,50 @@ REPLConsole.prototype.install = function(container) {
|
|
142
117
|
|
143
118
|
document.documentElement.addEventListener('mousemove', doDrag, false);
|
144
119
|
document.documentElement.addEventListener('mouseup', stopDrag, false);
|
145
|
-
}
|
120
|
+
}
|
121
|
+
|
122
|
+
function closeContainer(ev) {
|
123
|
+
container.parentNode.removeChild(container);
|
124
|
+
}
|
125
|
+
|
126
|
+
var shifted = false;
|
127
|
+
function shiftConsoleActions() {
|
128
|
+
if (consoleOuter.scrollHeight > consoleOuter.clientHeight) {
|
129
|
+
var widthDiff = document.documentElement.clientWidth - consoleOuter.clientWidth;
|
130
|
+
if (shifted || ! widthDiff) return;
|
131
|
+
shifted = true;
|
132
|
+
consoleActions.style.marginRight = widthDiff + 'px';
|
133
|
+
} else if (shifted) {
|
134
|
+
shifted = false;
|
135
|
+
consoleActions.style.marginRight = '0px';
|
136
|
+
}
|
137
|
+
}
|
146
138
|
|
147
139
|
// Initialize
|
148
|
-
this.
|
149
|
-
this.
|
140
|
+
this.outer = consoleOuter;
|
141
|
+
this.inner = findChild(this.outer, 'console-inner');
|
142
|
+
this.clipboard = findChild(container, 'clipboard');
|
143
|
+
this.remotePath = container.dataset.remotePath;
|
150
144
|
this.newPromptBox();
|
145
|
+
this.insertCss();
|
146
|
+
|
147
|
+
findChild(container, 'resizer').addEventListener('mousedown', resizeContainer);
|
148
|
+
findChild(consoleActions, 'close-button').addEventListener('click', closeContainer);
|
149
|
+
consoleOuter.addEventListener('DOMNodeInserted', shiftConsoleActions);
|
150
|
+
|
151
|
+
REPLConsole.currentSession = this;
|
152
|
+
};
|
153
|
+
|
154
|
+
// Add CSS styles dynamically. This probably doesnt work for IE <8.
|
155
|
+
REPLConsole.prototype.insertCss = function() {
|
156
|
+
if (document.getElementById(styleElementId)) {
|
157
|
+
return; // already inserted
|
158
|
+
}
|
159
|
+
var style = document.createElement('style');
|
160
|
+
style.type = 'text/css';
|
161
|
+
style.innerHTML = consoleStyleCss;
|
162
|
+
style.id = styleElementId;
|
163
|
+
document.getElementsByTagName('head')[0].appendChild(style);
|
151
164
|
};
|
152
165
|
|
153
166
|
REPLConsole.prototype.focus = function() {
|
@@ -367,7 +380,117 @@ REPLConsole.prototype.insertAtCurrent = function(char) {
|
|
367
380
|
};
|
368
381
|
|
369
382
|
REPLConsole.prototype.scrollToBottom = function() {
|
370
|
-
this.
|
383
|
+
this.outer.scrollTop = this.outer.scrollHeight;
|
371
384
|
};
|
372
385
|
|
386
|
+
// Change the binding of the console
|
387
|
+
REPLConsole.prototype.switchBindingTo = function(frameId, callback) {
|
388
|
+
var url = this.remotePath + "/trace";
|
389
|
+
var params = "frame_id=" + encodeURIComponent(frameId);
|
390
|
+
postRequest(url, params, callback);
|
391
|
+
};
|
392
|
+
|
393
|
+
/**
|
394
|
+
* Install the console into the element with a specific ID.
|
395
|
+
* Example: REPLConsole.installInto("target-id")
|
396
|
+
*/
|
397
|
+
REPLConsole.installInto = function(id) {
|
398
|
+
var consoleElement = document.getElementById(id);
|
399
|
+
var remotePath = consoleElement.dataset.remotePath;
|
400
|
+
var replConsole = new REPLConsole({
|
401
|
+
promptLabel: consoleElement.dataset.initialPrompt,
|
402
|
+
commandHandle: function(line) {
|
403
|
+
var _this = this;
|
404
|
+
var url = remotePath;
|
405
|
+
var params = "input=" + encodeURIComponent(line);
|
406
|
+
putRequest(url, params, function(xhr) {
|
407
|
+
var response = JSON.parse(xhr.responseText);
|
408
|
+
_this.writeOutput(response.output);
|
409
|
+
});
|
410
|
+
}
|
411
|
+
});
|
412
|
+
|
413
|
+
replConsole.install(consoleElement);
|
414
|
+
return replConsole;
|
415
|
+
};
|
416
|
+
|
417
|
+
// This is to store the latest single session, and the stored session
|
418
|
+
// is updated by the REPLConsole#install() method.
|
419
|
+
// It allows to operate the current session from the other scripts.
|
420
|
+
REPLConsole.currentSession = null;
|
421
|
+
|
422
|
+
// DOM helpers
|
423
|
+
function hasClass(el, className) {
|
424
|
+
var regex = new RegExp('(?:^|\\s)' + className + '(?!\\S)', 'g');
|
425
|
+
return el.className && el.className.match(regex);
|
426
|
+
}
|
427
|
+
|
428
|
+
function isNodeList(el) {
|
429
|
+
return typeof el.length === 'number' &&
|
430
|
+
typeof el.item === 'function';
|
431
|
+
}
|
432
|
+
|
433
|
+
function addClass(el, className) {
|
434
|
+
if (isNodeList(el)) {
|
435
|
+
for (var i = 0; i < el.length; ++ i) {
|
436
|
+
addClass(el[i], className);
|
437
|
+
}
|
438
|
+
} else {
|
439
|
+
el.className += " " + className;
|
440
|
+
}
|
441
|
+
}
|
442
|
+
|
443
|
+
function removeClass(el, className) {
|
444
|
+
var regex = new RegExp('(?:^|\\s)' + className + '(?!\\S)', 'g');
|
445
|
+
el.className = el.className.replace(regex, '');
|
446
|
+
}
|
447
|
+
|
448
|
+
function removeAllChildren(el) {
|
449
|
+
while (el.firstChild) {
|
450
|
+
el.removeChild(el.firstChild);
|
451
|
+
}
|
452
|
+
}
|
453
|
+
|
454
|
+
function findChild(el, className) {
|
455
|
+
for (var i = 0; i < el.childNodes.length; ++ i) {
|
456
|
+
if (hasClass(el.childNodes[i], className)) {
|
457
|
+
return el.childNodes[i];
|
458
|
+
}
|
459
|
+
}
|
460
|
+
}
|
461
|
+
|
462
|
+
function escapeHTML(html) {
|
463
|
+
return html
|
464
|
+
.replace(/&/g, '&')
|
465
|
+
.replace(/</g, '<')
|
466
|
+
.replace(/>/g, '>')
|
467
|
+
.replace(/"/g, '"')
|
468
|
+
.replace(/'/g, ''')
|
469
|
+
.replace(/`/g, '`');
|
470
|
+
}
|
471
|
+
|
472
|
+
// XHR helpers
|
473
|
+
function request(method, url, params, callback) {
|
474
|
+
var xhr = new XMLHttpRequest();
|
475
|
+
|
476
|
+
xhr.open(method, url, true);
|
477
|
+
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
478
|
+
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
|
479
|
+
xhr.send(params);
|
480
|
+
|
481
|
+
xhr.onreadystatechange = function() {
|
482
|
+
if (xhr.readyState === 4) {
|
483
|
+
callback(xhr);
|
484
|
+
}
|
485
|
+
}
|
486
|
+
}
|
487
|
+
|
488
|
+
function postRequest(url, params, callback) {
|
489
|
+
request("POST", url, params, callback);
|
490
|
+
}
|
491
|
+
|
492
|
+
function putRequest(url, params, callback) {
|
493
|
+
request("PUT", url, params, callback);
|
494
|
+
}
|
495
|
+
|
373
496
|
window.REPLConsole = REPLConsole;
|