rack-webconsole-pry 0.1.4

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.
@@ -0,0 +1,7 @@
1
+ # encoding: utf-8
2
+ module Rack
3
+ class Webconsole
4
+ # rack-webconsole version number.
5
+ VERSION = "0.1.4"
6
+ end
7
+ end
@@ -0,0 +1,81 @@
1
+ # encoding: utf-8
2
+ require 'rack/webconsole/repl'
3
+ require 'rack/webconsole/asset_helpers'
4
+ require 'rack/webconsole/assets'
5
+
6
+ require 'rack/webconsole/railtie' if defined?(Rails::Railtie)
7
+
8
+ # Rack is a modular webserver interface written by Christian Neukirchen.
9
+ #
10
+ # Learn more at: https://github.com/rack/rack
11
+ #
12
+ module Rack
13
+ # {Rack::Webconsole} is a Rack middleware that provides an interactive
14
+ # console à la Rails console, but for any kind of Rack application (Rails,
15
+ # Sinatra, Padrino...), accessible from your web application's front-end.
16
+ #
17
+ # For every request, it normally passes control to the {Assets} middleware,
18
+ # which injects needed JavaScript, CSS and HTML code for the console to work
19
+ # properly.
20
+ #
21
+ # It also exposes a special route used by the {Repl}, a Ruby evaluator which
22
+ # is responsible of keeping state between requests, remembering local
23
+ # variables and giving a true IRB-esque experience.
24
+ #
25
+ class Webconsole
26
+ @@config = {:inject_jquery => false, :key_code => "96"}
27
+
28
+ class << self
29
+ # Returns whether the Asset injecter must inject JQuery or not.
30
+ #
31
+ # @return [Boolean] whether to inject JQuery or not.
32
+ def inject_jquery
33
+ @@config[:inject_jquery]
34
+ end
35
+
36
+ # Sets whether the Asset injecter must inject JQuery or not.
37
+ #
38
+ # @param [Boolean] value whether to inject JQuery or not.
39
+ def inject_jquery=(value)
40
+ @@config[:inject_jquery] = value
41
+ end
42
+
43
+ # Returns key code used to start web console.
44
+ #
45
+ # @return [String] key code used at keypress event to start web console.
46
+ def key_code
47
+ @@config[:key_code]
48
+ end
49
+
50
+ # Sets key code used to start web console.
51
+ #
52
+ # @param [String] value key code used at keypress event to start web console.
53
+ def key_code=(value)
54
+ value = value.to_s unless value.is_a?(String)
55
+ @@config[:key_code] = value
56
+ end
57
+ end
58
+
59
+ # Honor the Rack contract by saving the passed Rack application in an ivar.
60
+ #
61
+ # @param [Rack::Application] app the previous Rack application in the
62
+ # middleware chain.
63
+ def initialize(app)
64
+ @app = app
65
+ end
66
+
67
+ # Decides where to send the request. In case the path is `/webconsole`
68
+ # (e.g. when calling the {Repl} endpoint), pass the request onto the
69
+ # {Repl}. Otherwise, pass it onto the {Assets} middleware, which will
70
+ # inject the needed assets for the Webconsole to work.
71
+ #
72
+ # @param [Hash] env a Rack request environment.
73
+ def call(env)
74
+ if env['PATH_INFO'] == '/webconsole'
75
+ Repl.new(@app).call(env)
76
+ else
77
+ Assets.new(@app).call(env)
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,3 @@
1
+ # encoding: utf-8
2
+ require 'rack'
3
+ require 'rack/webconsole'
@@ -0,0 +1 @@
1
+ <script type="text/javascript" src="http://code.jquery.com/jquery-1.6.2.min.js"></script>
@@ -0,0 +1,86 @@
1
+ #rack-webconsole {
2
+ opacity: 0.9;
3
+ z-index: 999;
4
+ background: #000;
5
+ color: #DDD;
6
+ font-family: monospace;
7
+ height: 40%;
8
+ position: fixed;
9
+ width: 100%;
10
+ bottom: 0px;
11
+ left: 0px;
12
+ right:0px;
13
+ outline-top: 3px solid #DEDEDE;
14
+ box-shadow: 0px -4px 5px rgba(0,0,0,0.5);
15
+ -moz-box-shadow: 0px -4px 5px rgba(0,0,0,0.5);
16
+ -webkit-box-shadow: 0px -4px 5px rgba(0,0,0,0.5);
17
+ font-size: 11px;
18
+ }
19
+ #rack-webconsole div.query{
20
+ margin-top: 10px;
21
+ font-weight: bold;
22
+ padding-top: 10px;
23
+ border-top: 1px dashed #333;
24
+ margin-bottom: 5px;
25
+ }
26
+ #rack-webconsole div.query_multiline{
27
+ font-weight: bold;
28
+ margin-bottom: 5px;
29
+ }
30
+ #rack-webconsole div.query:first-child{
31
+ margin-top: 0px;
32
+ padding-top: 0px;
33
+ border-top: none;
34
+ }
35
+ #rack-webconsole div.result{
36
+ font-weight: normal;
37
+ }
38
+ #rack-webconsole form div, #console form span {
39
+ font-size: 14px;
40
+ border: 0px;
41
+ font-family: monospace;
42
+ color: #FFF;
43
+ }
44
+ #rack-webconsole form div.results_wrapper{
45
+ width: 100%;
46
+ position: absolute;
47
+ overflow-x: auto;
48
+ top: 0;
49
+ bottom: 40px;
50
+ }
51
+ #rack-webconsole form div.results{
52
+ padding: 10px;
53
+ }
54
+ #rack-webconsole .prompt{
55
+ width: 30px;
56
+ text-align: center;
57
+ display: block;
58
+ float: left;
59
+ height: 25px;
60
+ line-height: 25px;
61
+ }
62
+ #rack-webconsole form div.input{
63
+ width: 100%;
64
+ position: absolute;
65
+ bottom: 0px;
66
+ background: #000;
67
+ }
68
+ #rack-webconsole form div.input input{
69
+ -webkit-box-sizing: border-box;
70
+ -moz-box-sizing: border-box;
71
+ box-sizing: border-box;
72
+ margin-top: 0px;
73
+ margin-bottom: 0px;
74
+ padding: 0px;
75
+ width: 100%;
76
+ font-size: 14px;
77
+ background: transparent;
78
+ border: 0px;
79
+ font-family: monospace;
80
+ color: #FFF;
81
+ }
82
+ #rack-webconsole .input .input_box{
83
+ margin-left: 30px;
84
+ margin-right: 10px;
85
+ display: block;
86
+ }
@@ -0,0 +1,15 @@
1
+ <div id="rack-webconsole" style="display:none">
2
+ <form accept-charset="UTF-8" action="/webconsole" method="post">
3
+ <input name="utf8" type="hidden" value="✓"/>
4
+ <div class="results_wrapper">
5
+ <div class="results">
6
+ </div>
7
+ </div>
8
+ <div class="input">
9
+ <span class="prompt">>></span>
10
+ <span class="input_box">
11
+ <input id="webconsole_query" name="webconsole_query" type="text" />
12
+ </span>
13
+ </div>
14
+ </form>
15
+ </div>
@@ -0,0 +1,169 @@
1
+ (function($) {
2
+
3
+ var webconsole = {
4
+ history:[],
5
+ pointer:0,
6
+ query:$('#webconsole_query')
7
+ }
8
+
9
+ $('#rack-webconsole form').submit(function(e){
10
+ e.preventDefault();
11
+ });
12
+
13
+ function componentToHex(c) {
14
+ var hex = c.toString(16);
15
+ return hex.length == 1 ? "0" + hex : hex;
16
+ }
17
+
18
+ function rgbToHex(r, g, b) {
19
+ return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
20
+ }
21
+ var prevStyle = {
22
+ color: "#ffffff",
23
+ bold: false,
24
+ underline: false
25
+ }
26
+ function bashColorToHtml(bcolor)
27
+ {
28
+ // colors
29
+ var textColor = rgbToHex(238, 238, 238);
30
+ var boldColor = rgbToHex(255, 255, 255);
31
+ var strColors = "[0;30m 238 238 238 \
32
+ [1;37m 255 255 255 \
33
+ [0;34m 150 203 254 \
34
+ [1;34m 181 220 254 \
35
+ [0;32m 168 255 96 \
36
+ [1;32m 206 255 172 \
37
+ [0;36m 198 197 254 \
38
+ [1;36m 223 223 254 \
39
+ [0;31m 255 108 96 \
40
+ [1;31m 255 182 176 \
41
+ [0;35m 255 115 253 \
42
+ [1;35m 255 156 254 \
43
+ [0;33m 255 255 182 \
44
+ [1;33m 255 255 203 \
45
+ [1;30m 124 124 124 \
46
+ [0;37m 238 238 238";
47
+ var colors = {};
48
+ var boldColors = {};
49
+ var matcher = /\[([0-9;]+)m\s+(\d+)\s+(\d+)\s+(\d+)/gm;
50
+ while ((r = matcher.exec(strColors)) != null) {
51
+ components = r[1].split(";")
52
+ if (components[0] == "0")
53
+ colors[components[1]] = rgbToHex(parseInt(r[2]), parseInt(r[3]), parseInt(r[4]));
54
+ else
55
+ boldColors[components[1]] = rgbToHex(parseInt(r[2]), parseInt(r[3]), parseInt(r[4]));
56
+ }
57
+ // set values
58
+ all = bcolor.split(/;/g)
59
+ if (all.indexOf("0") >= 0 && all.indexOf("0") > 0) // ignore anything before 0, since 0 resets
60
+ all.splice(0, all.indexOf("0"));
61
+ if (all.indexOf("0") >= 0)
62
+ prevStyle = {
63
+ color: textColor,
64
+ bold: false,
65
+ underline: false
66
+ };
67
+ if (all.indexOf("1") >= 0)
68
+ prevStyle['bold'] = true;
69
+ if (all.indexOf("4") >= 0)
70
+ prevStyle['underline'] = true;
71
+ if (prevStyle['bold'])
72
+ colorMap = boldColors;
73
+ else
74
+ colorMap = colors;
75
+ $.each(all, function(idx, val) {
76
+ if (colorMap[val] != undefined)
77
+ prevStyle['color'] = colorMap[val];
78
+ });
79
+ return 'color:'+prevStyle['color']+';font-weight:'+(prevStyle['bold'] ? 'bold' : 'normal')+
80
+ ';text-decoration:'+(prevStyle['underline'] ? 'underline' : 'none');
81
+ }
82
+ function parseBashString(str)
83
+ {
84
+ str = str.replace(/\u001B\[([0-9;]+)m/g, function(fm, sm) {
85
+ return '</span><span style="'+bashColorToHtml(sm)+'">';
86
+ });
87
+ str = str.replace(/\n/g, "<br>");
88
+ return '<span>'+str+'</span>';
89
+ }
90
+ $("#rack-webconsole form input").keyup(function(event) {
91
+ function escapeHTML(string) {
92
+ return(string.replace(/&/g,'&amp;').
93
+ replace(/>/g,'&gt;').
94
+ replace(/</g,'&lt;').
95
+ replace(/"/g,'&quot;')
96
+ );
97
+ };
98
+
99
+ // enter
100
+ if (event.which == 13) {
101
+ webconsole.history.push(webconsole.query.val());
102
+ webconsole.pointer = webconsole.history.length - 1;
103
+ $.ajax({
104
+ url: '/webconsole',
105
+ type: 'POST',
106
+ dataType: 'json',
107
+ data: ({query: webconsole.query.val(), token: "$TOKEN"}),
108
+ success: function (data) {
109
+ var query_class = data.previous_multi_line ? 'query_multiline' : 'query';
110
+ var result = "<div class='" + query_class + "'>" +
111
+ parseBashString(escapeHTML(data.prompt)) + "</div>";
112
+ if (!data.multi_line) {
113
+ result += "<div class='result'>" + parseBashString(escapeHTML(data.result)) + "</div>";
114
+ }
115
+ $("#rack-webconsole .results").append(result);
116
+ $("#rack-webconsole .results_wrapper").scrollTop(
117
+ $("#rack-webconsole .results").height()
118
+ );
119
+ }
120
+ });
121
+ webconsole.query.val('');
122
+ }
123
+
124
+ // up
125
+ if (event.which == 38) {
126
+ if (webconsole.pointer < 0) {
127
+ webconsole.query.val('');
128
+ } else {
129
+ if (webconsole.pointer == webconsole.history.length) {
130
+ webconsole.pointer = webconsole.history.length - 1;
131
+ }
132
+ webconsole.query.val(webconsole.history[webconsole.pointer]);
133
+ webconsole.pointer--;
134
+ }
135
+ }
136
+
137
+ // down
138
+ if (event.which == 40) {
139
+ if (webconsole.pointer == webconsole.history.length) {
140
+ webconsole.query.val('');
141
+ } else {
142
+ if (webconsole.pointer < 0) {
143
+ webconsole.pointer = 0;
144
+ }
145
+ webconsole.query.val(webconsole.history[webconsole.pointer]);
146
+ webconsole.pointer++;
147
+ }
148
+ }
149
+
150
+ });
151
+
152
+ $(document).ready(function() {
153
+ $(this).keypress(function(event) {
154
+ if (event.which == $KEY_CODE) {
155
+ $("#rack-webconsole").slideToggle('fast', function() {
156
+ if ($(this).is(':visible')) {
157
+ $("#rack-webconsole form input").focus();
158
+ $("#rack-webconsole .results_wrapper").scrollTop(
159
+ $("#rack-webconsole .results").height()
160
+ );
161
+ } else {
162
+ $("#rack-webconsole form input").blur();
163
+ }
164
+ });
165
+ event.preventDefault();
166
+ }
167
+ });
168
+ });
169
+ })(jQuery);
@@ -0,0 +1,36 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "rack/webconsole/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "rack-webconsole-pry"
7
+ s.version = Rack::Webconsole::VERSION
8
+ s.authors = ["Josep M. Bach", "Josep Jaume Rey", "Oriol Gual", "Jan Berdajs"]
9
+ s.email = ["mrbrdo@gmail.com"]
10
+ s.homepage = "http://github.com/mrbrdo/rack-webconsole"
11
+ s.summary = %q{Rack-based console inside your web applications, using pry}
12
+ s.description = %q{Rack-based console inside your web applications, using pry}
13
+
14
+ s.rubyforge_project = "rack-webconsole-pry"
15
+
16
+ s.add_runtime_dependency 'rack'
17
+ s.add_runtime_dependency 'multi_json', '>= 1.0.3'
18
+ s.add_runtime_dependency 'pry'
19
+
20
+ s.add_development_dependency 'minitest'
21
+ s.add_development_dependency 'purdytest'
22
+
23
+ # Since we can't have a git dependency in gemspec, we specify this
24
+ # dependency directly in the Gemfile. Once a new mocha version is released,
25
+ # we should uncomment this line and remove mocha from the Gemfile.
26
+ # s.add_development_dependency 'mocha'
27
+
28
+ s.add_development_dependency 'yard'
29
+ s.add_development_dependency 'bluecloth'
30
+ s.add_development_dependency 'rake'
31
+ s.add_development_dependency 'pry'
32
+
33
+ s.files = `git ls-files`.split("\n")
34
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
35
+ s.require_paths = ["lib"]
36
+ end
@@ -0,0 +1,56 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ class AssetClass
5
+ include Rack::Webconsole::AssetHelpers
6
+ end
7
+
8
+ module Rack
9
+ describe Webconsole::AssetHelpers do
10
+
11
+ describe '#html_code' do
12
+ it 'loads the html code' do
13
+ asset_class = AssetClass.new
14
+ html = asset_class.html_code
15
+
16
+ html.must_match /console/
17
+ html.must_match /results/
18
+ html.must_match /form/
19
+ end
20
+ end
21
+
22
+ describe '#css_code' do
23
+ it 'loads the css code' do
24
+ asset_class = AssetClass.new
25
+ css = asset_class.css_code
26
+
27
+ css.must_match /<style/
28
+ css.must_match /text\/css/
29
+ css.must_match /#console/
30
+ end
31
+ end
32
+
33
+ describe '#js_code' do
34
+ it 'loads the js code' do
35
+ asset_class = AssetClass.new
36
+ js = asset_class.js_code
37
+
38
+ js.must_match /\$\("#rack-webconsole"\)/
39
+ js.must_match /escapeHTML/
40
+ end
41
+ end
42
+
43
+ describe '#render' do
44
+ it 'knows how to replace $ vars' do
45
+ asset_class = AssetClass.new
46
+
47
+ text = "test $test test $test"
48
+ asset_class.render(text, :test => "123").must_equal("test 123 test 123")
49
+
50
+ text = "test $var1 test $var2"
51
+ asset_class.render(text, :var1 => "123", :var2 => "321").must_equal("test 123 test 321")
52
+ end
53
+ end
54
+
55
+ end
56
+ end