sabisu_rails 0.0.1.pre.beta

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 (40) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +8 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +109 -0
  6. data/Rakefile +1 -0
  7. data/app/assets/javascripts/sabisu_rails/application.js +12 -0
  8. data/app/assets/javascripts/sabisu_rails/sabisu.js.coffee +40 -0
  9. data/app/assets/stylesheets/sabisu_rails/application.css.scss +9 -0
  10. data/app/assets/stylesheets/sabisu_rails/explorer.css.scss +117 -0
  11. data/app/assets/stylesheets/sabisu_rails/furatto_overrides.scss +24 -0
  12. data/app/controllers/sabisu_rails/base_controller.rb +16 -0
  13. data/app/controllers/sabisu_rails/explorer_controller.rb +15 -0
  14. data/app/helpers/sabisu_rails/explorer_helper.rb +28 -0
  15. data/app/helpers/sabisu_rails_helper.rb +3 -0
  16. data/app/views/layouts/sabisu_rails.html.erb +28 -0
  17. data/app/views/sabisu_rails/explorer/index.html.erb +86 -0
  18. data/app/views/sabisu_rails/explorer/index.js.erb +6 -0
  19. data/config/routes.rb +3 -0
  20. data/lib/generators/sabisu_rails/install_generator.rb +17 -0
  21. data/lib/generators/sabisu_rails/templates/sabisu_rails.rb +34 -0
  22. data/lib/sabisu_rails/builders/base.rb +26 -0
  23. data/lib/sabisu_rails/builders/headers_builder.rb +6 -0
  24. data/lib/sabisu_rails/builders/url_params_builder.rb +6 -0
  25. data/lib/sabisu_rails/builders.rb +7 -0
  26. data/lib/sabisu_rails/engine.rb +5 -0
  27. data/lib/sabisu_rails/explorer.rb +35 -0
  28. data/lib/sabisu_rails/helpers/required.rb +14 -0
  29. data/lib/sabisu_rails/helpers.rb +5 -0
  30. data/lib/sabisu_rails/railtie.rb +22 -0
  31. data/lib/sabisu_rails/request.rb +28 -0
  32. data/lib/sabisu_rails/route_recognizer.rb +34 -0
  33. data/lib/sabisu_rails/version.rb +3 -0
  34. data/lib/sabisu_rails.rb +70 -0
  35. data/sabisu_rails.gemspec +30 -0
  36. data/vendor/assets/javascripts/sabisu_rails/KelpJSONView.js +120 -0
  37. data/vendor/assets/javascripts/sabisu_rails/pace.js +2 -0
  38. data/vendor/assets/stylesheets/sabisu_rails/KelpJSONView.css.scss +50 -0
  39. data/vendor/assets/stylesheets/sabisu_rails/pace.css +80 -0
  40. metadata +167 -0
@@ -0,0 +1,7 @@
1
+ module SabisuRails
2
+ module Builders
3
+ autoload :Base, 'sabisu_rails/builders/base'
4
+ autoload :UrlParamsBuilder, 'sabisu_rails/builders/url_params_builder'
5
+ autoload :HeadersBuilder, 'sabisu_rails/builders/headers_builder'
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ module SabisuRails
2
+ class Engine < Rails::Engine
3
+ isolate_namespace SabisuRails
4
+ end
5
+ end
@@ -0,0 +1,35 @@
1
+ module SabisuRails
2
+ class Explorer
3
+
4
+ include SabisuRails::Helpers::Required
5
+
6
+ attr_reader :resource, :uri_pattern, :http_method
7
+
8
+ def initialize(attrs = {})
9
+ @resource = attrs[:resource] || SabisuRails.default_resource
10
+ @uri_pattern = attrs[:uri_pattern]
11
+ @http_method = attrs[:http_method].nil? ? "get" : attrs[:http_method].downcase
12
+ end
13
+
14
+ # Method to retrieve the resource class name, such as User, Product, etc
15
+ def resource_class
16
+ @resource_class ||= @resource.singularize.classify.constantize
17
+ end
18
+
19
+ def resource_name
20
+ @resource_name ||= @resource.singularize
21
+ end
22
+
23
+ def resource_columns
24
+ resource_class.columns
25
+ end
26
+
27
+ def resource_attributes
28
+ resource_columns.map(&:name) - SabisuRails.ignored_attributes
29
+ end
30
+
31
+ def method_missing(meth, *args, &block)
32
+ resource_class.new.send(meth, *args, &block)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,14 @@
1
+ module SabisuRails
2
+ module Helpers
3
+ module Required
4
+
5
+ def required_attribute?(attr)
6
+ required_attributes.include? attr.to_sym
7
+ end
8
+
9
+ def required_attributes
10
+ @required_attributes ||= resource_class.validators.map(&:attributes).flatten.uniq
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,5 @@
1
+ module SabisuRails
2
+ module Helpers
3
+ autoload :Required, 'sabisu_rails/helpers/required'
4
+ end
5
+ end
@@ -0,0 +1,22 @@
1
+ require 'rails/railtie'
2
+
3
+ module SabisuRails
4
+ class Railtie < ::Rails::Railtie
5
+ config.eager_load_namespaces << SabisuRails
6
+
7
+ ActiveSupport.on_load :active_record do
8
+ if SabisuRails.resources.empty?
9
+ SabisuRails.resources = SabisuRails::RouteRecognizer.new.resources
10
+ SabisuRails.default_resource = SabisuRails.resources.first.to_s
11
+ end
12
+ SabisuRails.app_name = Rails.application.class.parent_name
13
+ end
14
+
15
+ config.after_initialize do
16
+ unless SabisuRails.configured?
17
+ warn '[Sabisu] Sabisu is not configured in the application and will use the default values.' +
18
+ ' We recommend you to check the file just created with the installer and setup it up.'
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,28 @@
1
+ module SabisuRails
2
+ class Request
3
+ include HTTParty
4
+
5
+ base_uri SabisuRails.base_api_uri
6
+ headers SabisuRails.api_headers
7
+
8
+ def initialize(explorer, body_params, params)
9
+ @explorer = explorer
10
+ @body_params = body_params || {}
11
+ @params = params || {}
12
+ @headers = SabisuRails::Builders::HeadersBuilder.new(@params[:headers]).build
13
+ @url_params = SabisuRails::Builders::UrlParamsBuilder.new(@params[:url_params]).build
14
+ end
15
+
16
+ def response
17
+ self.class.send(@explorer.http_method, "/#{@explorer.resource}/#{@explorer.uri_pattern}", body: resource_body_params, headers: @headers, query: @url_params)
18
+ end
19
+
20
+ def resource_body_params
21
+ body_params = {}
22
+
23
+ body_params[@explorer.resource_name] = @body_params.reject { |k, v| v.blank? }
24
+
25
+ body_params
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,34 @@
1
+ module SabisuRails
2
+ class RouteRecognizer
3
+ attr_reader :paths
4
+
5
+ # Based on @bantic solution - https://gist.github.com/bantic/5688232#file-rails_route_recognizer-rb
6
+ # To use this inside your app, call:
7
+ # `RouteRecognizer.new.initial_path_segments`
8
+ # This returns an array, e.g.: ['assets','blog','team','faq','users']
9
+
10
+ INITIAL_SEGMENT_REGEX = %r{^\/([^\/\(:]+)}
11
+ IGNORED_PATHS = ["assets", "rails", "sabisu_rails"]
12
+
13
+ def initialize
14
+ routes = Rails.application.routes.routes
15
+ @paths = routes.collect {|r| r.path.spec.to_s }
16
+ end
17
+
18
+ def initial_path_segments
19
+ @initial_path_segments ||= begin
20
+ paths.collect {|path| match_initial_path_segment(path)}.compact.uniq
21
+ end
22
+ end
23
+
24
+ def match_initial_path_segment(path)
25
+ if match = INITIAL_SEGMENT_REGEX.match(path)
26
+ match[1]
27
+ end
28
+ end
29
+
30
+ def resources
31
+ initial_path_segments - IGNORED_PATHS
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,3 @@
1
+ module SabisuRails
2
+ VERSION = "0.0.1-beta"
3
+ end
@@ -0,0 +1,70 @@
1
+ require 'httparty'
2
+
3
+ module SabisuRails
4
+ extend ActiveSupport::Autoload
5
+
6
+ autoload :Request
7
+ autoload :RouteRecognizer
8
+ autoload :Explorer
9
+ autoload :Helpers
10
+ autoload :Builders
11
+
12
+ # We ignore some attribues that might cause a collision between models
13
+ @@default_ignored_attributes = %w{ created_at updated_at id }
14
+
15
+ # We append the extra attributes you want to ignore to the default ones
16
+ mattr_accessor :ignored_attributes
17
+ @@ignored_attributes = @@ignored_attributes.to_a + @@default_ignored_attributes
18
+
19
+ # Base api uri for the endpoints
20
+ mattr_accessor :base_api_uri
21
+ @@base_api_uri = nil
22
+
23
+ # HTTP methods for the api
24
+ @@default_http_methods = %w{ GET POST PUT DELETE PATCH }
25
+
26
+ mattr_accessor :http_methods
27
+ @@http_methods = @@http_methods.to_a + @@default_http_methods
28
+
29
+ # Headers to include on each request
30
+ mattr_accessor :api_headers
31
+ @@api_headers = {}
32
+
33
+ # Layout
34
+ mattr_accessor :layout
35
+ @@layout = "sabisu_rails"
36
+
37
+ # Resources
38
+ mattr_accessor :resources
39
+ @@resources = []
40
+
41
+ # Authentication
42
+ mattr_accessor :authentication_username
43
+ @@authentication_username = "admin"
44
+
45
+ mattr_accessor :authentication_password
46
+ @@authentication_password = "sekret"
47
+
48
+ mattr_accessor :app_name
49
+ @@app_name = 'Sabisu'
50
+
51
+ mattr_accessor :default_resource
52
+
53
+ @@configured = false
54
+
55
+ def self.configured? #:nodoc:
56
+ @@configured
57
+ end
58
+
59
+ #Method to configure sabisu
60
+ def self.setup
61
+ @@configured = true
62
+
63
+ yield self
64
+ end
65
+
66
+ end
67
+
68
+ require 'sabisu_rails/railtie'
69
+ require 'sabisu_rails/engine'
70
+ require 'sabisu_rails/version'
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'sabisu_rails/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "sabisu_rails"
8
+ spec.version = SabisuRails::VERSION.dup
9
+ spec.authors = ["Abraham Kuri"]
10
+ spec.email = ["kurenn@icalialabs.com"]
11
+ spec.summary = %q{Smart API Explorer}
12
+ spec.description = %q{A smart api explorer for a rails app}
13
+ spec.homepage = "https://github.com/IcaliaLabs/sabisu-rails"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split("\n")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.rubyforge_project = "sabisu_rails"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.5"
24
+ spec.add_development_dependency "rake", "~> 10.3"
25
+ spec.add_development_dependency "debugger", "~> 1.6"
26
+
27
+ spec.add_dependency "activemodel", '~> 4.0'
28
+ spec.add_dependency "actionpack", '~> 4.0'
29
+ spec.add_dependency "httparty", "~> 0.13"
30
+ end
@@ -0,0 +1,120 @@
1
+ /*
2
+ * Kelp JSONView – http://kelp.phate.org/2011/11/kelp-json-view-json-syntax-highlighting.html
3
+ * Modded by Bramus! - http://www.bram.us/
4
+ */
5
+ $.extend(jQuery,
6
+ {
7
+ JSONView: function (json, container) {
8
+ var ob = (typeof json == 'string') ? JSON.parse(json) : json,
9
+ p,
10
+ l = [],
11
+ c = container;
12
+
13
+ var repeat = function (s, n) {
14
+ return new Array(n + 1).join(s);
15
+ };
16
+
17
+ // Check whether a string is an URL – Added by Bramus!
18
+ var isUrl = function(s) {
19
+ var regexp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/
20
+ return regexp.test(s);
21
+ };
22
+
23
+ // Escape string for output – Added by Bramus!
24
+ var htmlEntities = function(str) {
25
+ return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
26
+ }
27
+
28
+ //²£¥Í JSON µ²ºc¸ê®Æªº»¼°j¨ç¼Æ
29
+ //o ¨Ó·½ª«¥ó
30
+ //isar ¸ê®Æ¬O true ªº¸Ü¥Nªí³o¤@¦¸»¼°j¬°°}¦C¸ê®Æ
31
+ //s »¼°j¶¥¼h¼Æ
32
+ var r = function (o, isar, s) {
33
+ for (var n in o) {
34
+ var p = o[n];
35
+ switch (typeof p) {
36
+ case 'function':
37
+ break;
38
+ case 'string':
39
+ p = isUrl(p) ? '<a href="' + p + '">' + p + '</a>' : htmlEntities(p);
40
+ if (isar)
41
+ l.push({ Text: '<span class="jsonstring">"' + p + '"</span><span class="jsontag">,</span>', Step: s });
42
+ else
43
+ l.push({ Text: '<span class="jsonname">"' + n + '"</span><span class="jsontag">: </span><span class="jsonstring">"' + p + '"</span><span class="jsontag">,</span>', Step: s });
44
+ break;
45
+ case 'boolean':
46
+ if (isar)
47
+ l.push({ Text: '<span class="jsonboolean">"' + p + '"</span><span class="jsontag">,</span>', Step: s });
48
+ else
49
+ l.push({ Text: '<span class="jsonname">"' + n + '"</span><span class="jsontag">: </span><span class="jsonboolean">' + p + '</span><span class="jsontag">,</span>', Step: s });
50
+ break;
51
+ case 'number':
52
+ if (isar)
53
+ l.push({ Text: '<span class="jsonnumber">' + p + '</span><span class="jsontag">,</span>', Step: s });
54
+ else
55
+ l.push({ Text: '<span class="jsonname">"' + n + '"</span><span class="jsontag">: </span><span class="jsonnumber">' + p + '</span><span class="jsontag">,</span>', Step: s });
56
+ break;
57
+ case 'object':
58
+ if (p === null) {
59
+ if (isar)
60
+ l.push({ Text: '<span class="jsonnull">' + p + '</span><span class="jsontag">,</span>', Step: s });
61
+ else
62
+ l.push({ Text: '<span class="jsonname">"' + n + '"</span><span class="jsontag">: </span><span class="jsonnull">' + p + '</span><span class="jsontag">,</span>', Step: s });
63
+ }
64
+ else if (p.length == undefined) {
65
+ //object
66
+ if (!isar) {
67
+ l.push({ Text: '<span class="jsonname">"' + n + '"</span><span class="jsontag">:</span>', Step: s });
68
+ }
69
+ l.push({ Text: '<span class="jsontag">{</span>', Step: s });
70
+ r(p, false, s + 1);
71
+ l.push({ Text: '<span class="jsontag">},</span>', Step: s });
72
+ }
73
+ else {
74
+ //array
75
+ if (!isar) {
76
+ l.push({ Text: '<span class="jsonname">"' + n + '"</span><span class="jsontag">:</span>', Step: s });
77
+ }
78
+ l.push({ Text: '<span class="jsontag">[</span>', Step: s });
79
+ r(p, true, s + 1);
80
+ l.push({ Text: '<span class="jsontag">],</span>', Step: s });
81
+ }
82
+ break;
83
+ default: break;
84
+ }
85
+ }
86
+ var last = l.pop();
87
+ var ct = ',</span>';
88
+ if (last.Text.substr(last.Text.length - ct.length) == ct)
89
+ l.push({ Text: last.Text.replace(ct, '</span>'), Step: last.Step });
90
+ else
91
+ l.push(last);
92
+ };
93
+
94
+ //±N JavaScript Object ®æ¦¡¤Æ¶ë¶i array ¤¤
95
+ if (ob.length == undefined) {
96
+ //object
97
+ l.push({ Text: '<span class="jsontag">{</span>', Step: 0 });
98
+ r(ob, false, 1);
99
+ l.push({ Text: '<span class="jsontag">}</span>', Step: 0 });
100
+ }
101
+ else {
102
+ //array
103
+ l.push({ Text: '<span class="jsontag">[</span>', Step: 0 });
104
+ r(ob, true, 1);
105
+ l.push({ Text: '<span class="jsontag">]</span>', Step: 0 });
106
+ }
107
+
108
+ // Build HTML String
109
+ var html = '<ol>';
110
+ for (var index in l) {
111
+ var jobject = l[index];
112
+ html += '<li>' + repeat(' &nbsp; &nbsp;', jobject.Step) + jobject.Text + '</li>';
113
+ }
114
+ html += '</ol>';
115
+
116
+ // Inject HTML String into container
117
+ c.addClass('KelpJSONView').html(html);
118
+
119
+ }
120
+ });
@@ -0,0 +1,2 @@
1
+ /*! pace 0.5.1 */
2
+ (function(){var a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W=[].slice,X={}.hasOwnProperty,Y=function(a,b){function c(){this.constructor=a}for(var d in b)X.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},Z=[].indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(b in this&&this[b]===a)return b;return-1};for(t={catchupTime:500,initialRate:.03,minTime:500,ghostTime:500,maxProgressPerFrame:10,easeFactor:1.25,startOnPageLoad:!0,restartOnPushState:!0,restartOnRequestAfter:500,target:"body",elements:{checkInterval:100,selectors:["body"]},eventLag:{minSamples:10,sampleCount:3,lagThreshold:3},ajax:{trackMethods:["GET"],trackWebSockets:!0,ignoreURLs:[]}},B=function(){var a;return null!=(a="undefined"!=typeof performance&&null!==performance?"function"==typeof performance.now?performance.now():void 0:void 0)?a:+new Date},D=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame,s=window.cancelAnimationFrame||window.mozCancelAnimationFrame,null==D&&(D=function(a){return setTimeout(a,50)},s=function(a){return clearTimeout(a)}),F=function(a){var b,c;return b=B(),(c=function(){var d;return d=B()-b,d>=33?(b=B(),a(d,function(){return D(c)})):setTimeout(c,33-d)})()},E=function(){var a,b,c;return c=arguments[0],b=arguments[1],a=3<=arguments.length?W.call(arguments,2):[],"function"==typeof c[b]?c[b].apply(c,a):c[b]},u=function(){var a,b,c,d,e,f,g;for(b=arguments[0],d=2<=arguments.length?W.call(arguments,1):[],f=0,g=d.length;g>f;f++)if(c=d[f])for(a in c)X.call(c,a)&&(e=c[a],null!=b[a]&&"object"==typeof b[a]&&null!=e&&"object"==typeof e?u(b[a],e):b[a]=e);return b},p=function(a){var b,c,d,e,f;for(c=b=0,e=0,f=a.length;f>e;e++)d=a[e],c+=Math.abs(d),b++;return c/b},w=function(a,b){var c,d,e;if(null==a&&(a="options"),null==b&&(b=!0),e=document.querySelector("[data-pace-"+a+"]")){if(c=e.getAttribute("data-pace-"+a),!b)return c;try{return JSON.parse(c)}catch(f){return d=f,"undefined"!=typeof console&&null!==console?console.error("Error parsing inline pace options",d):void 0}}},g=function(){function a(){}return a.prototype.on=function(a,b,c,d){var e;return null==d&&(d=!1),null==this.bindings&&(this.bindings={}),null==(e=this.bindings)[a]&&(e[a]=[]),this.bindings[a].push({handler:b,ctx:c,once:d})},a.prototype.once=function(a,b,c){return this.on(a,b,c,!0)},a.prototype.off=function(a,b){var c,d,e;if(null!=(null!=(d=this.bindings)?d[a]:void 0)){if(null==b)return delete this.bindings[a];for(c=0,e=[];c<this.bindings[a].length;)this.bindings[a][c].handler===b?e.push(this.bindings[a].splice(c,1)):e.push(c++);return e}},a.prototype.trigger=function(){var a,b,c,d,e,f,g,h,i;if(c=arguments[0],a=2<=arguments.length?W.call(arguments,1):[],null!=(g=this.bindings)?g[c]:void 0){for(e=0,i=[];e<this.bindings[c].length;)h=this.bindings[c][e],d=h.handler,b=h.ctx,f=h.once,d.apply(null!=b?b:this,a),f?i.push(this.bindings[c].splice(e,1)):i.push(e++);return i}},a}(),null==window.Pace&&(window.Pace={}),u(Pace,g.prototype),C=Pace.options=u({},t,window.paceOptions,w()),T=["ajax","document","eventLag","elements"],P=0,R=T.length;R>P;P++)J=T[P],C[J]===!0&&(C[J]=t[J]);i=function(a){function b(){return U=b.__super__.constructor.apply(this,arguments)}return Y(b,a),b}(Error),b=function(){function a(){this.progress=0}return a.prototype.getElement=function(){var a;if(null==this.el){if(a=document.querySelector(C.target),!a)throw new i;this.el=document.createElement("div"),this.el.className="pace pace-active",document.body.className=document.body.className.replace(/pace-done/g,""),document.body.className+=" pace-running",this.el.innerHTML='<div class="pace-progress">\n <div class="pace-progress-inner"></div>\n</div>\n<div class="pace-activity"></div>',null!=a.firstChild?a.insertBefore(this.el,a.firstChild):a.appendChild(this.el)}return this.el},a.prototype.finish=function(){var a;return a=this.getElement(),a.className=a.className.replace("pace-active",""),a.className+=" pace-inactive",document.body.className=document.body.className.replace("pace-running",""),document.body.className+=" pace-done"},a.prototype.update=function(a){return this.progress=a,this.render()},a.prototype.destroy=function(){try{this.getElement().parentNode.removeChild(this.getElement())}catch(a){i=a}return this.el=void 0},a.prototype.render=function(){var a,b;return null==document.querySelector(C.target)?!1:(a=this.getElement(),a.children[0].style.width=""+this.progress+"%",(!this.lastRenderedProgress||this.lastRenderedProgress|0!==this.progress|0)&&(a.children[0].setAttribute("data-progress-text",""+(0|this.progress)+"%"),this.progress>=100?b="99":(b=this.progress<10?"0":"",b+=0|this.progress),a.children[0].setAttribute("data-progress",""+b)),this.lastRenderedProgress=this.progress)},a.prototype.done=function(){return this.progress>=100},a}(),h=function(){function a(){this.bindings={}}return a.prototype.trigger=function(a,b){var c,d,e,f,g;if(null!=this.bindings[a]){for(f=this.bindings[a],g=[],d=0,e=f.length;e>d;d++)c=f[d],g.push(c.call(this,b));return g}},a.prototype.on=function(a,b){var c;return null==(c=this.bindings)[a]&&(c[a]=[]),this.bindings[a].push(b)},a}(),O=window.XMLHttpRequest,N=window.XDomainRequest,M=window.WebSocket,v=function(a,b){var c,d,e,f;f=[];for(d in b.prototype)try{e=b.prototype[d],null==a[d]&&"function"!=typeof e?f.push(a[d]=e):f.push(void 0)}catch(g){c=g}return f},z=[],Pace.ignore=function(){var a,b,c;return b=arguments[0],a=2<=arguments.length?W.call(arguments,1):[],z.unshift("ignore"),c=b.apply(null,a),z.shift(),c},Pace.track=function(){var a,b,c;return b=arguments[0],a=2<=arguments.length?W.call(arguments,1):[],z.unshift("track"),c=b.apply(null,a),z.shift(),c},I=function(a){var b;if(null==a&&(a="GET"),"track"===z[0])return"force";if(!z.length&&C.ajax){if("socket"===a&&C.ajax.trackWebSockets)return!0;if(b=a.toUpperCase(),Z.call(C.ajax.trackMethods,b)>=0)return!0}return!1},j=function(a){function b(){var a,c=this;b.__super__.constructor.apply(this,arguments),a=function(a){var b;return b=a.open,a.open=function(d,e){return I(d)&&c.trigger("request",{type:d,url:e,request:a}),b.apply(a,arguments)}},window.XMLHttpRequest=function(b){var c;return c=new O(b),a(c),c},v(window.XMLHttpRequest,O),null!=N&&(window.XDomainRequest=function(){var b;return b=new N,a(b),b},v(window.XDomainRequest,N)),null!=M&&C.ajax.trackWebSockets&&(window.WebSocket=function(a,b){var d;return d=null!=b?new M(a,b):new M(a),I("socket")&&c.trigger("request",{type:"socket",url:a,protocols:b,request:d}),d},v(window.WebSocket,M))}return Y(b,a),b}(h),Q=null,x=function(){return null==Q&&(Q=new j),Q},H=function(a){var b,c,d,e;for(e=C.ajax.ignoreURLs,c=0,d=e.length;d>c;c++)if(b=e[c],"string"==typeof b){if(-1!==a.indexOf(b))return!0}else if(b.test(a))return!0;return!1},x().on("request",function(b){var c,d,e,f,g;return f=b.type,e=b.request,g=b.url,H(g)?void 0:Pace.running||C.restartOnRequestAfter===!1&&"force"!==I(f)?void 0:(d=arguments,c=C.restartOnRequestAfter||0,"boolean"==typeof c&&(c=0),setTimeout(function(){var b,c,g,h,i,j;if(b="socket"===f?e.readyState<2:0<(h=e.readyState)&&4>h){for(Pace.restart(),i=Pace.sources,j=[],c=0,g=i.length;g>c;c++){if(J=i[c],J instanceof a){J.watch.apply(J,d);break}j.push(void 0)}return j}},c))}),a=function(){function a(){var a=this;this.elements=[],x().on("request",function(){return a.watch.apply(a,arguments)})}return a.prototype.watch=function(a){var b,c,d,e;return d=a.type,b=a.request,e=a.url,H(e)?void 0:(c="socket"===d?new m(b):new n(b),this.elements.push(c))},a}(),n=function(){function a(a){var b,c,d,e,f,g,h=this;if(this.progress=0,null!=window.ProgressEvent)for(c=null,a.addEventListener("progress",function(a){return h.progress=a.lengthComputable?100*a.loaded/a.total:h.progress+(100-h.progress)/2}),g=["load","abort","timeout","error"],d=0,e=g.length;e>d;d++)b=g[d],a.addEventListener(b,function(){return h.progress=100});else f=a.onreadystatechange,a.onreadystatechange=function(){var b;return 0===(b=a.readyState)||4===b?h.progress=100:3===a.readyState&&(h.progress=50),"function"==typeof f?f.apply(null,arguments):void 0}}return a}(),m=function(){function a(a){var b,c,d,e,f=this;for(this.progress=0,e=["error","open"],c=0,d=e.length;d>c;c++)b=e[c],a.addEventListener(b,function(){return f.progress=100})}return a}(),d=function(){function a(a){var b,c,d,f;for(null==a&&(a={}),this.elements=[],null==a.selectors&&(a.selectors=[]),f=a.selectors,c=0,d=f.length;d>c;c++)b=f[c],this.elements.push(new e(b))}return a}(),e=function(){function a(a){this.selector=a,this.progress=0,this.check()}return a.prototype.check=function(){var a=this;return document.querySelector(this.selector)?this.done():setTimeout(function(){return a.check()},C.elements.checkInterval)},a.prototype.done=function(){return this.progress=100},a}(),c=function(){function a(){var a,b,c=this;this.progress=null!=(b=this.states[document.readyState])?b:100,a=document.onreadystatechange,document.onreadystatechange=function(){return null!=c.states[document.readyState]&&(c.progress=c.states[document.readyState]),"function"==typeof a?a.apply(null,arguments):void 0}}return a.prototype.states={loading:0,interactive:50,complete:100},a}(),f=function(){function a(){var a,b,c,d,e,f=this;this.progress=0,a=0,e=[],d=0,c=B(),b=setInterval(function(){var g;return g=B()-c-50,c=B(),e.push(g),e.length>C.eventLag.sampleCount&&e.shift(),a=p(e),++d>=C.eventLag.minSamples&&a<C.eventLag.lagThreshold?(f.progress=100,clearInterval(b)):f.progress=100*(3/(a+3))},50)}return a}(),l=function(){function a(a){this.source=a,this.last=this.sinceLastUpdate=0,this.rate=C.initialRate,this.catchup=0,this.progress=this.lastProgress=0,null!=this.source&&(this.progress=E(this.source,"progress"))}return a.prototype.tick=function(a,b){var c;return null==b&&(b=E(this.source,"progress")),b>=100&&(this.done=!0),b===this.last?this.sinceLastUpdate+=a:(this.sinceLastUpdate&&(this.rate=(b-this.last)/this.sinceLastUpdate),this.catchup=(b-this.progress)/C.catchupTime,this.sinceLastUpdate=0,this.last=b),b>this.progress&&(this.progress+=this.catchup*a),c=1-Math.pow(this.progress/100,C.easeFactor),this.progress+=c*this.rate*a,this.progress=Math.min(this.lastProgress+C.maxProgressPerFrame,this.progress),this.progress=Math.max(0,this.progress),this.progress=Math.min(100,this.progress),this.lastProgress=this.progress,this.progress},a}(),K=null,G=null,q=null,L=null,o=null,r=null,Pace.running=!1,y=function(){return C.restartOnPushState?Pace.restart():void 0},null!=window.history.pushState&&(S=window.history.pushState,window.history.pushState=function(){return y(),S.apply(window.history,arguments)}),null!=window.history.replaceState&&(V=window.history.replaceState,window.history.replaceState=function(){return y(),V.apply(window.history,arguments)}),k={ajax:a,elements:d,document:c,eventLag:f},(A=function(){var a,c,d,e,f,g,h,i;for(Pace.sources=K=[],g=["ajax","elements","document","eventLag"],c=0,e=g.length;e>c;c++)a=g[c],C[a]!==!1&&K.push(new k[a](C[a]));for(i=null!=(h=C.extraSources)?h:[],d=0,f=i.length;f>d;d++)J=i[d],K.push(new J(C));return Pace.bar=q=new b,G=[],L=new l})(),Pace.stop=function(){return Pace.trigger("stop"),Pace.running=!1,q.destroy(),r=!0,null!=o&&("function"==typeof s&&s(o),o=null),A()},Pace.restart=function(){return Pace.trigger("restart"),Pace.stop(),Pace.start()},Pace.go=function(){var a;return Pace.running=!0,q.render(),a=B(),r=!1,o=F(function(b,c){var d,e,f,g,h,i,j,k,m,n,o,p,s,t,u,v;for(k=100-q.progress,e=o=0,f=!0,i=p=0,t=K.length;t>p;i=++p)for(J=K[i],n=null!=G[i]?G[i]:G[i]=[],h=null!=(v=J.elements)?v:[J],j=s=0,u=h.length;u>s;j=++s)g=h[j],m=null!=n[j]?n[j]:n[j]=new l(g),f&=m.done,m.done||(e++,o+=m.tick(b));return d=o/e,q.update(L.tick(b,d)),q.done()||f||r?(q.update(100),Pace.trigger("done"),setTimeout(function(){return q.finish(),Pace.running=!1,Pace.trigger("hide")},Math.max(C.ghostTime,Math.max(C.minTime-(B()-a),0)))):c()})},Pace.start=function(a){u(C,a),Pace.running=!0;try{q.render()}catch(b){i=b}return document.querySelector(".pace")?(Pace.trigger("start"),Pace.go()):setTimeout(Pace.start,50)},"function"==typeof define&&define.amd?define(function(){return Pace}):"object"==typeof exports?module.exports=Pace:C.startOnPageLoad&&Pace.start()}).call(this);
@@ -0,0 +1,50 @@
1
+ .KelpJSONView
2
+ {
3
+ font-family: monospace;
4
+ font-weight: 400;
5
+ font-style:normal;
6
+ font-size:14px;
7
+ background-color: #3F3F3F;
8
+ padding: 6px;
9
+ }
10
+ .KelpJSONView ol {
11
+ background: transparent;
12
+ margin: 0;
13
+ padding: 0;
14
+ color: gainsboro;
15
+ list-style-position: inside;
16
+ list-style: none;
17
+ }
18
+ .KelpJSONView ol li
19
+ {
20
+ white-space:nowrap;
21
+ margin-bottom: 0;
22
+ }
23
+ .jsonname
24
+ {
25
+ color: #ddddbe;
26
+ }
27
+ .jsonstring
28
+ {
29
+ color: #CC9393;
30
+ }
31
+
32
+ .jsonstring a {
33
+ color: #c79696;
34
+ }
35
+ .jsonnull
36
+ {
37
+ color: #FFF;
38
+ }
39
+ .jsonnumber
40
+ {
41
+ color: #8CD0D3;
42
+ }
43
+ .jsonboolean
44
+ {
45
+ color: #b64B72;
46
+ }
47
+ .jsontag
48
+ {
49
+ color: gainsboro;
50
+ }
@@ -0,0 +1,80 @@
1
+ .pace {
2
+ -webkit-pointer-events: none;
3
+ pointer-events: none;
4
+ -webkit-user-select: none;
5
+ -moz-user-select: none;
6
+ user-select: none;
7
+ }
8
+
9
+ .pace-inactive {
10
+ display: none;
11
+ }
12
+
13
+ .pace .pace-progress {
14
+ background: #ea5d5f;
15
+ position: fixed;
16
+ z-index: 2000;
17
+ top: 0;
18
+ left: 0;
19
+ height: 2px;
20
+
21
+ -webkit-transition: width 1s;
22
+ -moz-transition: width 1s;
23
+ -o-transition: width 1s;
24
+ transition: width 1s;
25
+ }
26
+
27
+ .pace .pace-progress-inner {
28
+ display: block;
29
+ position: absolute;
30
+ right: 0px;
31
+ width: 100px;
32
+ height: 100%;
33
+ box-shadow: 0 0 10px #ea5d5f, 0 0 5px #ea5d5f;
34
+ opacity: 1.0;
35
+ -webkit-transform: rotate(3deg) translate(0px, -4px);
36
+ -moz-transform: rotate(3deg) translate(0px, -4px);
37
+ -ms-transform: rotate(3deg) translate(0px, -4px);
38
+ -o-transform: rotate(3deg) translate(0px, -4px);
39
+ transform: rotate(3deg) translate(0px, -4px);
40
+ }
41
+
42
+ .pace .pace-activity {
43
+ display: block;
44
+ position: fixed;
45
+ z-index: 2000;
46
+ top: 15px;
47
+ right: 15px;
48
+ width: 14px;
49
+ height: 14px;
50
+ border: solid 2px transparent;
51
+ border-top-color: #ea5d5f;
52
+ border-left-color: #ea5d5f;
53
+ border-radius: 10px;
54
+ -webkit-animation: pace-spinner 400ms linear infinite;
55
+ -moz-animation: pace-spinner 400ms linear infinite;
56
+ -ms-animation: pace-spinner 400ms linear infinite;
57
+ -o-animation: pace-spinner 400ms linear infinite;
58
+ animation: pace-spinner 400ms linear infinite;
59
+ }
60
+
61
+ @-webkit-keyframes pace-spinner {
62
+ 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); }
63
+ 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); }
64
+ }
65
+ @-moz-keyframes pace-spinner {
66
+ 0% { -moz-transform: rotate(0deg); transform: rotate(0deg); }
67
+ 100% { -moz-transform: rotate(360deg); transform: rotate(360deg); }
68
+ }
69
+ @-o-keyframes pace-spinner {
70
+ 0% { -o-transform: rotate(0deg); transform: rotate(0deg); }
71
+ 100% { -o-transform: rotate(360deg); transform: rotate(360deg); }
72
+ }
73
+ @-ms-keyframes pace-spinner {
74
+ 0% { -ms-transform: rotate(0deg); transform: rotate(0deg); }
75
+ 100% { -ms-transform: rotate(360deg); transform: rotate(360deg); }
76
+ }
77
+ @keyframes pace-spinner {
78
+ 0% { transform: rotate(0deg); transform: rotate(0deg); }
79
+ 100% { transform: rotate(360deg); transform: rotate(360deg); }
80
+ }