lecter 0.1.3 → 0.2.0

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/.all-contributorsrc +26 -0
  3. data/.circleci/config.yml +86 -0
  4. data/.github/ISSUE_TEMPLATE/bug_report.md +27 -0
  5. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  6. data/.github/PULL_REQUEST_TEMPLATE.md +16 -0
  7. data/.gitignore +2 -0
  8. data/.rubocop.yml +25 -0
  9. data/CHANGELOG.md +20 -0
  10. data/CONTRIBUTING.md +35 -0
  11. data/Gemfile +3 -2
  12. data/Gemfile.lock +37 -69
  13. data/LICENSE.txt +1 -1
  14. data/README.md +160 -35
  15. data/Rakefile +5 -3
  16. data/app/controllers/lecter/diagnosis_controller.rb +40 -54
  17. data/app/views/layouts/lecter.html.erb +258 -0
  18. data/app/views/lecter/diagnosis/new.html.erb +61 -0
  19. data/app/views/lecter/diagnosis/show.html.erb +54 -0
  20. data/bin/console +1 -0
  21. data/bin/rails +16 -0
  22. data/config/locales/en.yml +16 -0
  23. data/config/locales/ru.yml +16 -0
  24. data/config/routes.rb +7 -0
  25. data/lecter.gemspec +9 -5
  26. data/lib/lecter/engine.rb +7 -0
  27. data/lib/lecter/formatter_headers.rb +26 -0
  28. data/lib/lecter/formatter_payload.rb +35 -0
  29. data/lib/lecter/html_generator.rb +66 -0
  30. data/lib/lecter/html_row.rb +42 -0
  31. data/lib/lecter/rack.rb +32 -31
  32. data/lib/lecter/railtie.rb +9 -0
  33. data/lib/lecter/requester.rb +63 -0
  34. data/lib/lecter/trace_point.rb +30 -0
  35. data/lib/lecter/version.rb +3 -1
  36. data/lib/lecter.rb +15 -12
  37. metadata +50 -23
  38. data/.idea/encodings.xml +0 -6
  39. data/.idea/lecter.iml +0 -52
  40. data/.idea/misc.xml +0 -7
  41. data/.idea/modules.xml +0 -8
  42. data/.idea/workspace.xml +0 -857
  43. data/.travis.yml +0 -7
  44. data/app/assets/javascripts/highlight.pack.js +0 -2
  45. data/app/assets/stylesheets/railscasts.css +0 -106
  46. data/app/views/lecter/diagnosis/new.erb +0 -18
  47. data/app/views/lecter/diagnosis/show.slim +0 -56
@@ -1,70 +1,56 @@
1
- require 'rest-client'
2
- require 'slim-rails'
1
+ # frozen_string_literal: true
3
2
 
4
- class Lecter::DiagnosisController < ActionController::Base
5
- before_action :format_params, only: :create
3
+ module Lecter
4
+ class DiagnosisController < ActionController::Base
5
+ layout 'lecter'
6
+ before_action :format_request_data, only: :create
6
7
 
7
- def new
8
- end
8
+ def new; end
9
9
 
10
- def show
11
- end
10
+ def show
11
+ redirect_to new_diagnosis_path
12
+ end
12
13
 
13
- def create
14
- response =
15
- case diagnosis_params[:method]
16
- when 'get'
17
- ::RestClient.get(diagnosis_params[:endpoint], params: format_params)
18
- when 'post'
19
- ::RestClient.post(diagnosis_params[:endpoint], format_params)
14
+ def create
15
+ requester = Lecter::Requester.new(requester_params)
16
+ if requester.call
17
+ @file_listings = HtmlGenerator.new(requester.lines).call
18
+ render :show
19
+ else
20
+ flash[:error] = requester.error_message
21
+ render :new
20
22
  end
23
+ end
21
24
 
22
- return render :new unless response
23
-
24
- prepare_data(response.body)
25
- render :show
26
- rescue URI::InvalidURIError
27
- flash[:error] = 'Wrong url'
28
- return render :new
29
- end
30
-
31
- private
25
+ private
32
26
 
33
- def diagnosis_params
34
- params.permit(:endpoint, :params, :method)
35
- end
27
+ def diagnosis_params
28
+ params.permit(:endpoint, :body_raw, :method, :headers)
29
+ end
36
30
 
37
- def prepare_data(items)
38
- @lines = []
39
- @items = items.split(';')
40
- @items.each do |item|
41
- file = item.split(' ')[0]
42
- if @lines.last.is_a?(Hash) && @lines.last.keys.first.to_s == file
43
- @lines.last[file] = @lines.last[file] << item.split(' ')[1].to_i
44
- else
45
- @lines << {"#{file}" => [item.split(' ')[1].to_i]}
46
- end
31
+ def requester_params
32
+ {
33
+ method: diagnosis_params[:method].downcase.to_sym,
34
+ url: diagnosis_params[:endpoint],
35
+ payload: formatter_payload.result,
36
+ headers: formatted_headers.result
37
+ }
47
38
  end
48
- end
49
39
 
50
- def format_params
51
- @format_params ||= begin
52
- return {} unless diagnosis_params[:params].present?
40
+ def format_request_data
41
+ formatters = [formatter_payload, formatted_headers]
42
+ return if formatters.all?(&:call)
53
43
 
54
- json_parse(diagnosis_params[:params]).merge(lecter_analysis_parameter)
55
- rescue JSON::ParserError
56
- flash[:error] = 'Wrong parameters'
57
- return render :new
44
+ flash[:error] = formatters.map(&:error_message).join(', ')
45
+ render :new
58
46
  end
59
- end
60
47
 
61
- def lecter_analysis_parameter
62
- { lecter_analysis: true }
63
- end
48
+ def formatter_payload
49
+ @formatter_payload ||= Lecter::FormatterPayload.new(diagnosis_params[:body_raw])
50
+ end
64
51
 
65
- def json_parse(string)
66
- string = '{' + string + '}' unless string.match(/\A{.*}\z/)
67
- string.gsub!('=>', ':').gsub!(/(“|”)/, '"')
68
- JSON.parse(string)
52
+ def formatted_headers
53
+ @formatted_headers ||= Lecter::FormatterHeaders.new(diagnosis_params[:headers])
54
+ end
69
55
  end
70
56
  end
@@ -0,0 +1,258 @@
1
+ <html>
2
+ <head>
3
+ <title><%= yield(:title) %></title>
4
+ <%= javascript_include_tag '//code.jquery.com/jquery-1.12.4.js', '//code.jquery.com/ui/1.12.1/jquery-ui.js' %>
5
+ <%= javascript_include_tag 'https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js' %>
6
+ <%= stylesheet_link_tag 'https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css' %>
7
+ </head>
8
+
9
+ <style>
10
+ .hljs {
11
+ display: block;
12
+ overflow-x: auto;
13
+ padding: 0.5em;
14
+ background: #232323;
15
+ color: #e6e1dc;
16
+ }
17
+
18
+ .hljs-comment,
19
+ .hljs-quote {
20
+ color: #bc9458;
21
+ font-style: italic;
22
+ }
23
+
24
+ .hljs-keyword,
25
+ .hljs-selector-tag {
26
+ color: #c26230;
27
+ }
28
+
29
+ .hljs-string,
30
+ .hljs-number,
31
+ .hljs-regexp,
32
+ .hljs-variable,
33
+ .hljs-template-variable {
34
+ color: #a5c261;
35
+ }
36
+
37
+ .hljs-subst {
38
+ color: #519f50;
39
+ }
40
+
41
+ .hljs-tag,
42
+ .hljs-name {
43
+ color: #e8bf6a;
44
+ }
45
+
46
+ .hljs-type {
47
+ color: #da4939;
48
+ }
49
+
50
+
51
+ .hljs-symbol,
52
+ .hljs-bullet,
53
+ .hljs-built_in,
54
+ .hljs-builtin-name,
55
+ .hljs-attr,
56
+ .hljs-link {
57
+ color: #6d9cbe;
58
+ }
59
+
60
+ .hljs-params {
61
+ color: #d0d0ff;
62
+ }
63
+
64
+ .hljs-attribute {
65
+ color: #cda869;
66
+ }
67
+
68
+ .hljs-meta {
69
+ color: #9b859d;
70
+ }
71
+
72
+ .hljs-title,
73
+ .hljs-section {
74
+ color: #ffc66d;
75
+ }
76
+
77
+ .hljs-addition {
78
+ background-color: #144212;
79
+ color: #e6e1dc;
80
+ display: inline-block;
81
+ width: 100%;
82
+ }
83
+
84
+ .hljs-deletion {
85
+ background-color: #600;
86
+ color: #e6e1dc;
87
+ display: inline-block;
88
+ width: 100%;
89
+ }
90
+
91
+ .hljs-selector-class {
92
+ color: #9b703f;
93
+ }
94
+
95
+ .hljs-selector-id {
96
+ color: #8b98ab;
97
+ }
98
+
99
+ .hljs-emphasis {
100
+ font-style: italic;
101
+ }
102
+
103
+ .hljs-strong {
104
+ font-weight: bold;
105
+ }
106
+
107
+ .hljs-link {
108
+ text-decoration: underline;
109
+ }
110
+
111
+ /* diagnosis/show.slim */
112
+
113
+
114
+ .down {
115
+ border-left: 5px solid transparent;
116
+ border-right: 5px solid transparent;
117
+ border-top: 5px solid black;
118
+ margin: 10px 7px 0 5px;
119
+ }
120
+
121
+ .ui-accordion .ui-accordion-header {
122
+ font-size: 78%;
123
+ }
124
+
125
+ .sidebar {
126
+ float: left;
127
+ }
128
+
129
+ .sidebar > .sidebar-wrapper {
130
+ width: 235px;
131
+ position: fixed;
132
+ margin: 49px 33px 0 0;
133
+ overflow-y: scroll;
134
+ top: 82px;
135
+ bottom: 40px;
136
+ }
137
+
138
+ .sidebar-wrapper > ul {
139
+ list-style-type: none;
140
+ height: calc(100% - 40px);
141
+ }
142
+
143
+ .sidebar-wrapper > ul > li {
144
+ margin-bottom: 3px;
145
+ }
146
+
147
+ .sidebar-wrapper > ul > li > a {
148
+ text-decoration: none;
149
+ color: inherit;
150
+ display: block;
151
+ font-size: 13px;
152
+ text-inline: 1.5;
153
+ }
154
+
155
+ .sidebar-wrapper > ul > li > a:hover {
156
+ color: #7d7d7d;
157
+ }
158
+
159
+ .right {
160
+ float: left;
161
+ padding-left: 10px;
162
+ width: 70%;
163
+ margin-left: 295px;
164
+ }
165
+
166
+ .listing {
167
+ display: none;
168
+ padding: 1em 2.2em;
169
+ overflow: auto;
170
+ border-bottom-right-radius: 4px;
171
+ border: 0.5px solid;
172
+ border-top-width: 0;
173
+ border-bottom-left-radius: 4px;
174
+ background: #efefef;
175
+ }
176
+
177
+ .filename {
178
+ cursor: pointer;
179
+ position: relative;
180
+ margin: 2px 0 0 0;
181
+ padding: .5em .5em .5em .7em;
182
+ border: solid 0.1px;
183
+ background: #efefef;
184
+ }
185
+
186
+ /* layouts/lecter.slim */
187
+
188
+ body {
189
+ font-family: "Helvetica Neue", "Helvetica", Arial, "Open Sans", sans-serif;
190
+ font-size: 15px;
191
+ line-height: 1.6;
192
+ -webkit-font-smoothing: antialiased;
193
+ }
194
+
195
+ .body-wrapper {
196
+ overflow: hidden;
197
+ *zoom: 1;
198
+ margin-top: 50px;
199
+ margin-bottom: 50px;
200
+ display: block;
201
+ padding: 0 20px;
202
+ }
203
+
204
+ .nav {
205
+ font-weight: 500;
206
+ background: #0b4e22;
207
+ border-bottom: 1px solid #cccccc;
208
+ }
209
+
210
+ .nav-inner {
211
+ display: block;
212
+ max-width: 955px;
213
+ padding: 1px 20px;
214
+ }
215
+
216
+ .nav-inner > ul {
217
+ list-style-type: none;
218
+ }
219
+
220
+ .nav-inner > ul > li > a {
221
+ text-decoration: none;
222
+ font-weight: 600;
223
+ color: white;
224
+ letter-spacing: 0.4px;
225
+ }
226
+
227
+ .ul {
228
+ -webkit-justify-content: space-between;
229
+ justify-content: space-between;
230
+ list-style-type: none;
231
+ margin: 0;
232
+ padding: 8px 2px 8px;
233
+ display: -webkit-flex;
234
+ display: flex;
235
+ }
236
+
237
+ .li {
238
+ -webkit-flex: 0 1 auto;
239
+ flex: 0 1 auto;
240
+ display: list-item;
241
+ text-align: -webkit-match-parent;
242
+ list-style-type: none;
243
+ }
244
+
245
+ .nav-inner > li > a {
246
+ text-decoration: none;
247
+ font-weight: 400;
248
+ color: white;
249
+ letter-spacing: 0.4px;
250
+ }
251
+ </style>
252
+
253
+ <body>
254
+ <div class="container">
255
+ <%= yield %>
256
+ </div>
257
+ </body>
258
+ </html>
@@ -0,0 +1,61 @@
1
+ <%= content_for :title, t('.title') %>
2
+
3
+ <div class="container">
4
+ <h2><%= t('.title') %></h2>
5
+
6
+ <%= form_tag diagnosis_path do %>
7
+ <% flash.each do |key, value| %>
8
+ <div class="col-sm-2 col-form-label">
9
+ <%= value %>
10
+ </div>
11
+ <% end %>
12
+ <div class="row my-3">
13
+ <%= label_tag t('.method'), nil, class: 'col-sm-2 col-form-label' %>
14
+ <div class="col-sm">
15
+ <%= select_tag :method, options_for_select(Lecter::AVAILABLE_METHODS, Lecter::DEFAULT_METHOD) %>
16
+ </div>
17
+ <div class="col-sm gray">
18
+ Choose one
19
+ </div>
20
+ </div>
21
+ <div class="row my-3">
22
+ <%= label_tag t('.endpoint'), nil, class: 'col-sm-2 col-form-label' %>
23
+ <div class="col-sm">
24
+ <%= text_field_tag :endpoint, nil, class: 'form-control', placeholder: 'Endpoint' %>
25
+ </div>
26
+ <div class="col-sm gray">
27
+ localhost:3000/posts
28
+ </div>
29
+ </div>
30
+ <div class="row my-3">
31
+ <%= label_tag t('.headers'), nil, class: 'col-sm-2 col-form-label' %>
32
+ <div class="col-sm">
33
+ <%= text_field_tag :headers, nil, class: 'form-control', placeholder: 'Headers' %>
34
+ </div>
35
+ <div class="col-sm gray">
36
+ content_type=text/html,accept=*/*
37
+ </div>
38
+ </div>
39
+ <div class="row my-3">
40
+ <%= label_tag t('.body_raw'), nil, class: 'col-sm-2 col-form-label' %>
41
+ <div class="col-sm">
42
+ <%= text_area_tag :body_raw, nil, rows: 10, class: 'form-control', placeholder: 'Body(raw)' %>
43
+ </div>
44
+ <div class="col-sm gray">
45
+ "post" => {
46
+ "title" => "New title",
47
+ "description" => "Desciption"
48
+ }
49
+ </div>
50
+ </div>
51
+
52
+ </p>
53
+ <%= submit_tag t('.send'), class: 'btn btn-primary' %>
54
+ <% end %>
55
+ </div>
56
+
57
+ <style>
58
+ .gray {
59
+ color: #727a82
60
+ }
61
+ </style>
@@ -0,0 +1,54 @@
1
+ <%= content_for :title, t('.title') %>
2
+
3
+ <div class="container">
4
+ <h2><%= t('.executed_code') %></h2>
5
+ </div>
6
+
7
+ <div class="row py-3">
8
+ <div class="col-3 order-2" style="width: 280px;">
9
+ <div class="sticky-top">
10
+ <ul>
11
+ <% @file_listings.each_with_index do |file_listing, index| %>
12
+ <li>
13
+ <a href="#anchor<%= index %>" class="nav-link link-dark">
14
+ <%= raw(file_listing.file_path.split('/').last) %>
15
+ </a>
16
+ </li>
17
+ <% end %>
18
+ </ul>
19
+ </div>
20
+ </div>
21
+
22
+ <div class="col">
23
+ <div class="accordion" id="accordionExample">
24
+ <% @file_listings.each_with_index do |file_listing, index| %>
25
+ <div class="accordion-item">
26
+ <h2 class="accordion-header" id="headingOne">
27
+ <button class="accordion-button" type="button" data-bs-toggle="collapse"
28
+ data-bs-target="#collapse<%=index%>" aria-expanded="true" aria-controls="collapse<%=index%>"
29
+ id="anchor<%=index%>"
30
+ >
31
+ <%= file_listing.file_path.split('/').last %>
32
+ </button>
33
+ </h2>
34
+ <div id="collapse<%=index%>" class="accordion-collapse collapse show" aria-labelledby="heading<%=index%>>" data-bs-parent="#accordionExample">
35
+ <div class="accordion-body">
36
+ <pre>
37
+ <code><% file_listing.html_rows.each do |html_row| %><%= raw(html_row) %><% end %></code>
38
+ </pre>
39
+ </div>
40
+ </div>
41
+ </div>
42
+ <% end %>
43
+ </div>
44
+ </div>
45
+ </div>
46
+
47
+ <script>
48
+ /*! highlight.js v9.15.8 | BSD3 License | git.io/hljslicense */
49
+ !function(e){var n="object"==typeof window&&window||"object"==typeof self&&self;"undefined"!=typeof exports?e(exports):n&&(n.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return n.hljs}))}(function(a){var f=[],u=Object.keys,N={},c={},n=/^(no-?highlight|plain|text)$/i,s=/\blang(?:uage)?-([\w-]+)\b/i,t=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,r={case_insensitive:"cI",lexemes:"l",contains:"c",keywords:"k",subLanguage:"sL",className:"cN",begin:"b",beginKeywords:"bK",end:"e",endsWithParent:"eW",illegal:"i",excludeBegin:"eB",excludeEnd:"eE",returnBegin:"rB",returnEnd:"rE",relevance:"r",variants:"v",IDENT_RE:"IR",UNDERSCORE_IDENT_RE:"UIR",NUMBER_RE:"NR",C_NUMBER_RE:"CNR",BINARY_NUMBER_RE:"BNR",RE_STARTERS_RE:"RSR",BACKSLASH_ESCAPE:"BE",APOS_STRING_MODE:"ASM",QUOTE_STRING_MODE:"QSM",PHRASAL_WORDS_MODE:"PWM",C_LINE_COMMENT_MODE:"CLCM",C_BLOCK_COMMENT_MODE:"CBCM",HASH_COMMENT_MODE:"HCM",NUMBER_MODE:"NM",C_NUMBER_MODE:"CNM",BINARY_NUMBER_MODE:"BNM",CSS_NUMBER_MODE:"CSSNM",REGEXP_MODE:"RM",TITLE_MODE:"TM",UNDERSCORE_TITLE_MODE:"UTM",COMMENT:"C",beginRe:"bR",endRe:"eR",illegalRe:"iR",lexemesRe:"lR",terminators:"t",terminator_end:"tE"},b="</span>",h={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0};function _(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function E(e){return e.nodeName.toLowerCase()}function v(e,n){var t=e&&e.exec(n);return t&&0===t.index}function l(e){return n.test(e)}function g(e){var n,t={},r=Array.prototype.slice.call(arguments,1);for(n in e)t[n]=e[n];return r.forEach(function(e){for(n in e)t[n]=e[n]}),t}function R(e){var a=[];return function e(n,t){for(var r=n.firstChild;r;r=r.nextSibling)3===r.nodeType?t+=r.nodeValue.length:1===r.nodeType&&(a.push({event:"start",offset:t,node:r}),t=e(r,t),E(r).match(/br|hr|img|input/)||a.push({event:"stop",offset:t,node:r}));return t}(e,0),a}function i(e){if(r&&!e.langApiRestored){for(var n in e.langApiRestored=!0,r)e[n]&&(e[r[n]]=e[n]);(e.c||[]).concat(e.v||[]).forEach(i)}}function m(o){function s(e){return e&&e.source||e}function c(e,n){return new RegExp(s(e),"m"+(o.cI?"i":"")+(n?"g":""))}!function n(t,e){if(!t.compiled){if(t.compiled=!0,t.k=t.k||t.bK,t.k){function r(t,e){o.cI&&(e=e.toLowerCase()),e.split(" ").forEach(function(e){var n=e.split("|");a[n[0]]=[t,n[1]?Number(n[1]):1]})}var a={};"string"==typeof t.k?r("keyword",t.k):u(t.k).forEach(function(e){r(e,t.k[e])}),t.k=a}t.lR=c(t.l||/\w+/,!0),e&&(t.bK&&(t.b="\\b("+t.bK.split(" ").join("|")+")\\b"),t.b||(t.b=/\B|\b/),t.bR=c(t.b),t.endSameAsBegin&&(t.e=t.b),t.e||t.eW||(t.e=/\B|\b/),t.e&&(t.eR=c(t.e)),t.tE=s(t.e)||"",t.eW&&e.tE&&(t.tE+=(t.e?"|":"")+e.tE)),t.i&&(t.iR=c(t.i)),null==t.r&&(t.r=1),t.c||(t.c=[]),t.c=Array.prototype.concat.apply([],t.c.map(function(e){return function(n){return n.v&&!n.cached_variants&&(n.cached_variants=n.v.map(function(e){return g(n,{v:null},e)})),n.cached_variants||n.eW&&[g(n)]||[n]}("self"===e?t:e)})),t.c.forEach(function(e){n(e,t)}),t.starts&&n(t.starts,e);var i=t.c.map(function(e){return e.bK?"\\.?(?:"+e.b+")\\.?":e.b}).concat([t.tE,t.i]).map(s).filter(Boolean);t.t=i.length?c(function(e,n){for(var t=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./,r=0,a="",i=0;i<e.length;i++){var o=r,c=s(e[i]);for(0<i&&(a+=n);0<c.length;){var u=t.exec(c);if(null==u){a+=c;break}a+=c.substring(0,u.index),c=c.substring(u.index+u[0].length),"\\"==u[0][0]&&u[1]?a+="\\"+String(Number(u[1])+o):(a+=u[0],"("==u[0]&&r++)}}return a}(i,"|"),!0):{exec:function(){return null}}}}(o)}function C(e,n,i,t){function c(e,n,t,r){var a='<span class="'+(r?"":h.classPrefix);return e?(a+=e+'">')+n+(t?"":b):n}function o(){E+=null!=l.sL?function(){var e="string"==typeof l.sL;if(e&&!N[l.sL])return _(g);var n=e?C(l.sL,g,!0,f[l.sL]):O(g,l.sL.length?l.sL:void 0);return 0<l.r&&(R+=n.r),e&&(f[l.sL]=n.top),c(n.language,n.value,!1,!0)}():function(){var e,n,t,r,a,i,o;if(!l.k)return _(g);for(r="",n=0,l.lR.lastIndex=0,t=l.lR.exec(g);t;)r+=_(g.substring(n,t.index)),a=l,i=t,void 0,o=s.cI?i[0].toLowerCase():i[0],(e=a.k.hasOwnProperty(o)&&a.k[o])?(R+=e[1],r+=c(e[0],_(t[0]))):r+=_(t[0]),n=l.lR.lastIndex,t=l.lR.exec(g);return r+_(g.substr(n))}(),g=""}function u(e){E+=e.cN?c(e.cN,"",!0):"",l=Object.create(e,{parent:{value:l}})}function r(e,n){if(g+=e,null==n)return o(),0;var t=function(e,n){var t,r,a;for(t=0,r=n.c.length;t<r;t++)if(v(n.c[t].bR,e))return n.c[t].endSameAsBegin&&(n.c[t].eR=(a=n.c[t].bR.exec(e)[0],new RegExp(a.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&"),"m"))),n.c[t]}(n,l);if(t)return t.skip?g+=n:(t.eB&&(g+=n),o(),t.rB||t.eB||(g=n)),u(t),t.rB?0:n.length;var r=function e(n,t){if(v(n.eR,t)){for(;n.endsParent&&n.parent;)n=n.parent;return n}if(n.eW)return e(n.parent,t)}(l,n);if(r){var a=l;for(a.skip?g+=n:(a.rE||a.eE||(g+=n),o(),a.eE&&(g=n));l.cN&&(E+=b),l.skip||l.sL||(R+=l.r),(l=l.parent)!==r.parent;);return r.starts&&(r.endSameAsBegin&&(r.starts.eR=r.eR),u(r.starts)),a.rE?0:n.length}if(function(e,n){return!i&&v(n.iR,e)}(n,l))throw new Error('Illegal lexeme "'+n+'" for mode "'+(l.cN||"<unnamed>")+'"');return g+=n,n.length||1}var s=B(e);if(!s)throw new Error('Unknown language: "'+e+'"');m(s);var a,l=t||s,f={},E="";for(a=l;a!==s;a=a.parent)a.cN&&(E=c(a.cN,"",!0)+E);var g="",R=0;try{for(var d,p,M=0;l.t.lastIndex=M,d=l.t.exec(n);)p=r(n.substring(M,d.index),d[0]),M=d.index+p;for(r(n.substr(M)),a=l;a.parent;a=a.parent)a.cN&&(E+=b);return{r:R,value:E,language:e,top:l}}catch(e){if(e.message&&-1!==e.message.indexOf("Illegal"))return{r:0,value:_(n)};throw e}}function O(t,e){e=e||h.languages||u(N);var r={r:0,value:_(t)},a=r;return e.filter(B).filter(M).forEach(function(e){var n=C(e,t,!1);n.language=e,n.r>a.r&&(a=n),n.r>r.r&&(a=r,r=n)}),a.language&&(r.second_best=a),r}function d(e){return h.tabReplace||h.useBR?e.replace(t,function(e,n){return h.useBR&&"\n"===e?"<br>":h.tabReplace?n.replace(/\t/g,h.tabReplace):""}):e}function o(e){var n,t,r,a,i,o=function(e){var n,t,r,a,i=e.className+" ";if(i+=e.parentNode?e.parentNode.className:"",t=s.exec(i))return B(t[1])?t[1]:"no-highlight";for(n=0,r=(i=i.split(/\s+/)).length;n<r;n++)if(l(a=i[n])||B(a))return a}(e);l(o)||(h.useBR?(n=document.createElementNS("http://www.w3.org/1999/xhtml","div")).innerHTML=e.innerHTML.replace(/\n/g,"").replace(/<br[ \/]*>/g,"\n"):n=e,i=n.textContent,r=o?C(o,i,!0):O(i),(t=R(n)).length&&((a=document.createElementNS("http://www.w3.org/1999/xhtml","div")).innerHTML=r.value,r.value=function(e,n,t){var r=0,a="",i=[];function o(){return e.length&&n.length?e[0].offset!==n[0].offset?e[0].offset<n[0].offset?e:n:"start"===n[0].event?e:n:e.length?e:n}function c(e){a+="<"+E(e)+f.map.call(e.attributes,function(e){return" "+e.nodeName+'="'+_(e.value).replace('"',"&quot;")+'"'}).join("")+">"}function u(e){a+="</"+E(e)+">"}function s(e){("start"===e.event?c:u)(e.node)}for(;e.length||n.length;){var l=o();if(a+=_(t.substring(r,l[0].offset)),r=l[0].offset,l===e){for(i.reverse().forEach(u);s(l.splice(0,1)[0]),(l=o())===e&&l.length&&l[0].offset===r;);i.reverse().forEach(c)}else"start"===l[0].event?i.push(l[0].node):i.pop(),s(l.splice(0,1)[0])}return a+_(t.substr(r))}(t,R(a),i)),r.value=d(r.value),e.innerHTML=r.value,e.className=function(e,n,t){var r=n?c[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}(e.className,o,r.language),e.result={language:r.language,re:r.r},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.r}))}function p(){if(!p.called){p.called=!0;var e=document.querySelectorAll("pre code");f.forEach.call(e,o)}}function B(e){return e=(e||"").toLowerCase(),N[e]||N[c[e]]}function M(e){var n=B(e);return n&&!n.disableAutodetect}return a.highlight=C,a.highlightAuto=O,a.fixMarkup=d,a.highlightBlock=o,a.configure=function(e){h=g(h,e)},a.initHighlighting=p,a.initHighlightingOnLoad=function(){addEventListener("DOMContentLoaded",p,!1),addEventListener("load",p,!1)},a.registerLanguage=function(n,e){var t=N[n]=e(a);i(t),t.aliases&&t.aliases.forEach(function(e){c[e]=n})},a.listLanguages=function(){return u(N)},a.getLanguage=B,a.autoDetection=M,a.inherit=g,a.IR=a.IDENT_RE="[a-zA-Z]\\w*",a.UIR=a.UNDERSCORE_IDENT_RE="[a-zA-Z_]\\w*",a.NR=a.NUMBER_RE="\\b\\d+(\\.\\d+)?",a.CNR=a.C_NUMBER_RE="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",a.BNR=a.BINARY_NUMBER_RE="\\b(0b[01]+)",a.RSR=a.RE_STARTERS_RE="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",a.BE=a.BACKSLASH_ESCAPE={b:"\\\\[\\s\\S]",r:0},a.ASM=a.APOS_STRING_MODE={cN:"string",b:"'",e:"'",i:"\\n",c:[a.BE]},a.QSM=a.QUOTE_STRING_MODE={cN:"string",b:'"',e:'"',i:"\\n",c:[a.BE]},a.PWM=a.PHRASAL_WORDS_MODE={b:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},a.C=a.COMMENT=function(e,n,t){var r=a.inherit({cN:"comment",b:e,e:n,c:[]},t||{});return r.c.push(a.PWM),r.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),r},a.CLCM=a.C_LINE_COMMENT_MODE=a.C("//","$"),a.CBCM=a.C_BLOCK_COMMENT_MODE=a.C("/\\*","\\*/"),a.HCM=a.HASH_COMMENT_MODE=a.C("#","$"),a.NM=a.NUMBER_MODE={cN:"number",b:a.NR,r:0},a.CNM=a.C_NUMBER_MODE={cN:"number",b:a.CNR,r:0},a.BNM=a.BINARY_NUMBER_MODE={cN:"number",b:a.BNR,r:0},a.CSSNM=a.CSS_NUMBER_MODE={cN:"number",b:a.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},a.RM=a.REGEXP_MODE={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[a.BE,{b:/\[/,e:/\]/,r:0,c:[a.BE]}]},a.TM=a.TITLE_MODE={cN:"title",b:a.IR,r:0},a.UTM=a.UNDERSCORE_TITLE_MODE={cN:"title",b:a.UIR,r:0},a.METHOD_GUARD={b:"\\.\\s*"+a.UIR,r:0},a});hljs.registerLanguage("ruby",function(e){var b="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?",r={keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor",literal:"true false nil"},c={cN:"doctag",b:"@[A-Za-z]+"},a={b:"#<",e:">"},s=[e.C("#","$",{c:[c]}),e.C("^\\=begin","^\\=end",{c:[c],r:10}),e.C("^__END__","\\n$")],n={cN:"subst",b:"#\\{",e:"}",k:r},t={cN:"string",c:[e.BE,n],v:[{b:/'/,e:/'/},{b:/"/,e:/"/},{b:/`/,e:/`/},{b:"%[qQwWx]?\\(",e:"\\)"},{b:"%[qQwWx]?\\[",e:"\\]"},{b:"%[qQwWx]?{",e:"}"},{b:"%[qQwWx]?<",e:">"},{b:"%[qQwWx]?/",e:"/"},{b:"%[qQwWx]?%",e:"%"},{b:"%[qQwWx]?-",e:"-"},{b:"%[qQwWx]?\\|",e:"\\|"},{b:/\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/},{b:/<<(-?)\w+$/,e:/^\s*\w+$/}]},i={cN:"params",b:"\\(",e:"\\)",endsParent:!0,k:r},d=[t,a,{cN:"class",bK:"class module",e:"$|;",i:/=/,c:[e.inherit(e.TM,{b:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"}),{b:"<\\s*",c:[{b:"("+e.IR+"::)?"+e.IR}]}].concat(s)},{cN:"function",bK:"def",e:"$|;",c:[e.inherit(e.TM,{b:b}),i].concat(s)},{b:e.IR+"::"},{cN:"symbol",b:e.UIR+"(\\!|\\?)?:",r:0},{cN:"symbol",b:":(?!\\s)",c:[t,{b:b}],r:0},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{b:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{cN:"params",b:/\|/,e:/\|/,k:r},{b:"("+e.RSR+"|unless)\\s*",k:"unless",c:[a,{cN:"regexp",c:[e.BE,n],i:/\n/,v:[{b:"/",e:"/[a-z]*"},{b:"%r{",e:"}[a-z]*"},{b:"%r\\(",e:"\\)[a-z]*"},{b:"%r!",e:"![a-z]*"},{b:"%r\\[",e:"\\][a-z]*"}]}].concat(s),r:0}].concat(s);n.c=d;var l=[{b:/^\s*=>/,starts:{e:"$",c:i.c=d}},{cN:"meta",b:"^([>?]>|[\\w#]+\\(\\w+\\):\\d+:\\d+>|(\\w+-)?\\d+\\.\\d+\\.\\d(p\\d+)?[^>]+>)",starts:{e:"$",c:d}}];return{aliases:["rb","gemspec","podspec","thor","irb"],k:r,i:/\/\*/,c:s.concat(l).concat(d)}});
50
+
51
+ $(document).ready(function(){
52
+ hljs.initHighlighting();
53
+ })
54
+ </script>
data/bin/console CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'bundler/setup'
4
5
  require 'lecter'
data/bin/rails ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # This command will automatically be run when you run "rails" with Rails gems
5
+ # installed from the root of your application.
6
+
7
+ ENGINE_ROOT = File.expand_path('..', __dir__)
8
+ ENGINE_PATH = File.expand_path('../lib/lecter/engine', __dir__)
9
+ APP_PATH = File.expand_path('../test/dummy/config/application', __dir__)
10
+
11
+ # Set up gems listed in the Gemfile.
12
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
13
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
14
+
15
+ require 'rails/all'
16
+ require 'rails/engine/commands'
@@ -0,0 +1,16 @@
1
+ en:
2
+ layouts:
3
+ lecter:
4
+ new_diagnosis: 'New diagnosis'
5
+ lecter:
6
+ diagnosis:
7
+ show:
8
+ title: 'Diagnosis results'
9
+ executed_code: 'Executed code:'
10
+ new:
11
+ title: 'New diagnosis'
12
+ endpoint: 'Endpoint'
13
+ body_raw: 'Body (raw)'
14
+ method: 'HTTP method'
15
+ send: 'Send request'
16
+ headers: 'Headers'
@@ -0,0 +1,16 @@
1
+ ru:
2
+ layouts:
3
+ lecter:
4
+ new_diagnosis: 'Новый диагноз'
5
+ lecter:
6
+ diagnosis:
7
+ show:
8
+ title: 'Диагноз'
9
+ executed_code: 'Используемый код:'
10
+ new:
11
+ title: 'Новый диагноз'
12
+ endpoint: 'Абсолютный путь'
13
+ body_raw: 'Тело запроса'
14
+ method: 'HTTP метод'
15
+ send: 'Послать запрос'
16
+ headers: 'Заголовки'
data/config/routes.rb ADDED
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ Lecter::Engine.routes.draw do
4
+ root 'diagnosis#new'
5
+
6
+ resource :diagnosis, only: %w[new create show], controller: :diagnosis
7
+ end
data/lecter.gemspec CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  lib = File.expand_path('lib', __dir__)
2
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
5
  require 'lecter/version'
@@ -8,8 +10,9 @@ Gem::Specification.new do |spec|
8
10
  spec.authors = ['Neodelf']
9
11
  spec.email = ['neodelf@gmail.com']
10
12
 
11
- spec.summary = %q{Write a short summary, because RubyGems requires one.}
12
- spec.description = %q{Write a longer description or delete this line.}
13
+ spec.summary = 'Show executable code by request.'
14
+ spec.description = 'The main purpose of that gem is helping developers to understand which '\
15
+ 'code executes by request.<br>'
13
16
  spec.homepage = 'https://github.com/neodelf/lecter'
14
17
  spec.license = 'MIT'
15
18
 
@@ -21,7 +24,7 @@ Gem::Specification.new do |spec|
21
24
 
22
25
  # Specify which files should be added to the gem when it is released.
23
26
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
27
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
25
28
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
26
29
  end
27
30
  spec.bindir = 'exe'
@@ -29,9 +32,10 @@ Gem::Specification.new do |spec|
29
32
  spec.require_paths = ['lib']
30
33
 
31
34
  spec.add_development_dependency 'bundler', '~> 2.0'
32
- spec.add_development_dependency 'rake', '~> 10.0'
35
+ spec.add_development_dependency 'rake', '~> 13.0'
33
36
  spec.add_development_dependency 'rspec', '~> 3.0'
37
+ spec.add_development_dependency 'rubocop'
34
38
 
35
- spec.add_runtime_dependency 'slim-rails'
36
39
  spec.add_runtime_dependency 'rest-client'
40
+ spec.add_runtime_dependency 'simplecov', '0.17.1'
37
41
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lecter
4
+ class Engine < ::Rails::Engine
5
+ isolate_namespace Lecter
6
+ end
7
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lecter
4
+ class FormatterHeaders
5
+ WRONG_HEADERS_MSG = 'Wrong headers'
6
+ attr_reader :result, :error_message
7
+
8
+ def initialize(headers)
9
+ @dirty_headers = headers
10
+ end
11
+
12
+ def call
13
+ @result = dirty_headers
14
+ .split(',')
15
+ .map { |header_with_value| header_with_value.split('=') }
16
+ .to_h
17
+ rescue StandardError
18
+ @error_message = WRONG_HEADERS_MSG
19
+ false
20
+ end
21
+
22
+ private
23
+
24
+ attr_accessor :dirty_headers
25
+ end
26
+ end