lurker 0.6.9 → 0.6.10

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 (34) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +1 -2
  3. data.tar.gz.sig +0 -0
  4. data/README.md +8 -1
  5. data/lib/lurker.rb +9 -1
  6. data/lib/lurker/cli.rb +148 -129
  7. data/lib/lurker/endpoint.rb +7 -3
  8. data/lib/lurker/json/schema.rb +12 -3
  9. data/lib/lurker/json/{writter.rb → writer.rb} +2 -2
  10. data/lib/lurker/presenters/base_presenter.rb +9 -34
  11. data/lib/lurker/presenters/endpoint_presenter.rb +16 -6
  12. data/lib/lurker/presenters/service_presenter.rb +29 -5
  13. data/lib/lurker/rendering_controller.rb +14 -7
  14. data/lib/lurker/service.rb +18 -12
  15. data/lib/lurker/templates/documentation.md.tt +1 -0
  16. data/lib/lurker/templates/javascripts/lurker.js +1 -1
  17. data/lib/lurker/templates/layouts/application.html.erb +54 -57
  18. data/lib/lurker/templates/layouts/print.html.erb +29 -0
  19. data/lib/lurker/templates/lurker/rendering/_endpoint.html.erb +36 -0
  20. data/lib/lurker/templates/lurker/rendering/_service.html.erb +7 -0
  21. data/lib/lurker/templates/lurker/rendering/_submit_form.html.erb +16 -16
  22. data/lib/lurker/templates/lurker/rendering/all.html.erb +5 -0
  23. data/lib/lurker/templates/lurker/rendering/index.html.erb +1 -10
  24. data/lib/lurker/templates/lurker/rendering/show.html.erb +1 -37
  25. data/lib/lurker/templates/public/application.css +1 -1
  26. data/lib/lurker/templates/public/application.js +1 -1
  27. data/lib/lurker/templates/stylesheets/application.scss +3 -0
  28. data/lib/lurker/version.rb +1 -1
  29. data/tasks/build.rake +2 -2
  30. data/tasks/generate.rake +2 -0
  31. data/templates/lurker_app.rb +0 -1
  32. metadata +8 -4
  33. metadata.gz.sig +0 -0
  34. data/lib/lurker/templates/meta_service.md.erb +0 -20
@@ -21,6 +21,16 @@ module Lurker
21
21
  parse_schema(schema)
22
22
  end
23
23
 
24
+ def documentation_uri(extension = 'md')
25
+ @uri.to_s.sub(%r{^file:(//)?}, '').sub(/(\.json)?(\.yml)?(\.erb)?$/, ".#{extension}")
26
+ end
27
+
28
+ def documentation
29
+ open(documentation_uri).read
30
+ rescue
31
+ @schema['description']
32
+ end
33
+
24
34
  def root?
25
35
  root_schema.blank?
26
36
  end
@@ -40,8 +50,7 @@ module Lurker
40
50
  end
41
51
 
42
52
  def replace!(property, property_schema)
43
- @schema[property] = Lurker::Json::Parser.plain(subschema_options)
44
- .parse_property(property, property_schema)
53
+ @schema[property] = @parser.plain.parse_property(property, property_schema)
45
54
  end
46
55
 
47
56
  def reorder!
@@ -54,7 +63,7 @@ module Lurker
54
63
  end
55
64
 
56
65
  def to_json(options = {})
57
- hashify(@schema, options).to_json
66
+ to_hash(options).to_json
58
67
  end
59
68
 
60
69
  def to_yaml(options = {})
@@ -1,6 +1,6 @@
1
1
  module Lurker
2
2
  module Json
3
- class Writter
3
+ class Writer
4
4
  class << self
5
5
  def write(schema, path)
6
6
  new(path).write(schema)
@@ -16,7 +16,7 @@ module Lurker
16
16
  write_to_file(schema)
17
17
 
18
18
  extract_references(schema).each do |reference|
19
- Lurker::Json::Writter.write(reference, reference.original_uri.path)
19
+ Lurker::Json::Writer.write(reference, reference.original_uri.path)
20
20
  end
21
21
  end
22
22
 
@@ -9,16 +9,6 @@ class Lurker::BasePresenter
9
9
  @options = options
10
10
  end
11
11
 
12
- def render_erb(erb_name, binding = get_binding)
13
- template_path = path_for_template(erb_name)
14
- template = ERB.new(File.read(template_path), nil, '-')
15
- template.result(binding)
16
- end
17
-
18
- def get_binding
19
- binding
20
- end
21
-
22
12
  def html_directory
23
13
  options[:url_base_path] || options[:html_directory] || ""
24
14
  end
@@ -27,8 +17,12 @@ class Lurker::BasePresenter
27
17
  options[:url_base_path] || '/'
28
18
  end
29
19
 
30
- def css_path
31
- File.join(html_directory, "styles.css")
20
+ def assets
21
+ options[:assets] || {}
22
+ end
23
+
24
+ def asset_path(asset)
25
+ "#{html_directory}/#{assets[asset] || asset}"
32
26
  end
33
27
 
34
28
  def index_path(subdirectory = "")
@@ -51,27 +45,8 @@ class Lurker::BasePresenter
51
45
  EOS
52
46
  end
53
47
 
54
- def render(*args)
55
- rendering_controller.render_to_string(*args)
56
- end
57
-
58
- protected
59
-
60
- def path_for_template(filename)
61
- template_dir = options[:template_directory]
62
- template_path = File.join(template_dir, filename) if template_dir
63
- if template_path.nil? || !File.exist?(template_path)
64
- template_path = File.join(File.dirname(__FILE__), "../templates", filename)
65
- end
66
- template_path
67
- end
68
-
69
- def rendering_controller
70
- return @rendering_controller if @rendering_controller
71
- @rendering_controller = Lurker::RenderingController.new
72
- instance_variables.each do |var|
73
- @rendering_controller.instance_variable_set(var, instance_variable_get(var))
74
- end
75
- @rendering_controller
48
+ def markup(content)
49
+ Lurker.safe_require 'kramdown'
50
+ defined?(Kramdown) ? Kramdown::Document.new(content).to_html : content
76
51
  end
77
52
  end
@@ -2,6 +2,9 @@
2
2
  class Lurker::EndpointPresenter < Lurker::BasePresenter
3
3
  attr_accessor :service_presenter, :endpoint, :endpoint_presenter
4
4
 
5
+ extend Forwardable
6
+ def_delegators :endpoint, :url_params
7
+
5
8
  def initialize(endpoint, options = {})
6
9
  super(options)
7
10
  @endpoint = endpoint
@@ -10,12 +13,15 @@ class Lurker::EndpointPresenter < Lurker::BasePresenter
10
13
  end
11
14
 
12
15
  def to_html(options={})
13
- @service_presenter = service_presenter
14
- @endpoint_presenter = self
15
- @url_params = endpoint.url_params
16
- @post_params = example_request.json
17
- @title = "#{service_presenter.title} | #{title}"
18
- render('show', options)
16
+ controller = Lurker::RenderingController.new
17
+ controller.service_presenter = service_presenter
18
+ controller.endpoint_presenter = self
19
+ controller.instance_variable_set :@title, "#{service_presenter.title} | #{title}"
20
+ controller.render_to_string 'show', options
21
+ end
22
+
23
+ def documentation
24
+ markup @endpoint.documentation
19
25
  end
20
26
 
21
27
  def relative_path(extension = ".html")
@@ -34,6 +40,10 @@ class Lurker::EndpointPresenter < Lurker::BasePresenter
34
40
  endpoint.prefix || endpoint.path.split("/").first
35
41
  end
36
42
 
43
+ def post_params
44
+ example_request.json
45
+ end
46
+
37
47
  def zws_ify(str)
38
48
  # zero-width-space, makes long lines friendlier for breaking
39
49
  # str.gsub(/\//, '&#8203;/') if str
@@ -1,3 +1,5 @@
1
+ require 'active_support/inflector'
2
+
1
3
  # An BasePresenter for Lurker::Service
2
4
  class Lurker::ServicePresenter < Lurker::BasePresenter
3
5
  attr_reader :service
@@ -11,10 +13,20 @@ class Lurker::ServicePresenter < Lurker::BasePresenter
11
13
  @filtering_block = block
12
14
  end
13
15
 
14
- # TODO move to controller
15
- def to_html(&block)
16
- @service_presenter = self
17
- render('index')
16
+ def to_html(options={}, &block)
17
+ controller = Lurker::RenderingController.new
18
+ controller.service_presenter = self
19
+ controller.render_to_string 'index', options
20
+ end
21
+
22
+ def to_print(options = {})
23
+ controller = Lurker::RenderingController.new
24
+ controller.service_presenter = self
25
+ controller.render_to_string 'all', { layout: 'print' }.merge(options)
26
+ end
27
+
28
+ def documentation
29
+ markup @service.documentation
18
30
  end
19
31
 
20
32
  def title
@@ -46,13 +58,25 @@ class Lurker::ServicePresenter < Lurker::BasePresenter
46
58
  end
47
59
 
48
60
  def slug_name
49
- service.name.downcase.gsub(/[ \/]/, '_')
61
+ @slug_name ||= service.name.downcase.gsub(/[ \/]/, '_')
62
+ end
63
+
64
+ def url_name
65
+ @url_name ||= ActiveSupport::Inflector.parameterize(name, '_')
50
66
  end
51
67
 
52
68
  def url(extension = ".html")
53
69
  '%s-%s%s' % [@endpoint.path, @endpoint.verb, extension]
54
70
  end
55
71
 
72
+ def footer
73
+ @footer ||= options[:footer].present? ? "Revision&nbsp;#{options[:footer]}".html_safe : ''
74
+ end
75
+
76
+ def lurker
77
+ @lurker ||= options[:lurker] || ''
78
+ end
79
+
56
80
  def endpoints
57
81
  unless @endpoints
58
82
  @endpoints = []
@@ -2,28 +2,30 @@ require 'ostruct'
2
2
  require 'abstract_controller'
3
3
  require 'action_view'
4
4
  require 'action_dispatch/http/mime_type'
5
+ require 'action_dispatch/routing'
5
6
 
6
7
  module Lurker
7
8
  class RenderingController < ::AbstractController::Base
8
9
  # Include all the concerns we need to make this work
10
+ include AbstractController::Logger
9
11
  include AbstractController::Helpers
10
12
  include AbstractController::Rendering
11
- include ActionView::Rendering if defined?(ActionView::Rendering)
12
- include ActionView::Layouts if defined?(ActionView::Layouts) # Rails 4.1.x
13
+ include AbstractController::AssetPaths
13
14
  include AbstractController::Layouts if defined?(AbstractController::Layouts) # Rails 3.2.x, 4.0.x
15
+ include ActionView::Layouts if defined?(ActionView::Layouts) # Rails 4.1.x
16
+ include ActionView::Rendering if defined?(ActionView::Rendering)
14
17
  include ActionView::Context
15
18
 
16
- self.view_paths = File.join(File.dirname(__FILE__), "templates")
19
+ attr_writer :service_presenter, :endpoint_presenter
17
20
 
18
21
  # Define additional helpers, this one is for csrf_meta_tag
19
- helper_method :protect_against_forgery?, :tag_with_anchor
22
+ helper_method :title, :tag_with_anchor, :protect_against_forgery?
20
23
 
21
24
  # override the layout in your subclass if needed.
22
25
  layout 'application'
23
26
 
24
- # we are not in a browser, no need for this
25
- def protect_against_forgery?
26
- false
27
+ def title
28
+ [@service_presenter.try(:title), @endpoint_presenter.try(:title)].compact.join ' | '
27
29
  end
28
30
 
29
31
  def tag_with_anchor(tag, content, anchor_slug = nil)
@@ -37,6 +39,11 @@ module Lurker
37
39
  EOS
38
40
  end
39
41
 
42
+ # we are not in a browser, no need for this
43
+ def protect_against_forgery?
44
+ false
45
+ end
46
+
40
47
  # so that your flash calls still work
41
48
  def flash
42
49
  {}
@@ -3,8 +3,17 @@ require 'yaml'
3
3
  # Services represent a group of Lurker API endpoints in a directory
4
4
  class Lurker::Service
5
5
  attr_reader :service_dir, :schema
6
+ attr_writer :documentation
6
7
  attr_accessor :opened_endpoints
7
8
  SUFFIX = '.service.yml'
9
+ DEFAULT_SCHEMA = {
10
+ name: '',
11
+ basePath: '',
12
+ description: '',
13
+ domains: {},
14
+ consumes: %w(application/x-www-form-urlencode application/json),
15
+ produces: %w(application/json)
16
+ }
8
17
 
9
18
  def self.default_service
10
19
  new(Lurker.service_path)
@@ -15,16 +24,9 @@ class Lurker::Service
15
24
  @service_dir = File.expand_path(service_dir)
16
25
  @service_filename = service_name
17
26
  @schema = if persisted? && (schema = YAML.load_file(service_path)).is_a?(Hash)
18
- Lurker::Json::Schema.new(schema)
27
+ Lurker::Json::Schema.new(schema, uri: service_path)
19
28
  else
20
- Lurker::Json::Schema.new(
21
- 'name' => service_filename,
22
- 'basePath' => '',
23
- 'description' => '',
24
- 'domains' => {},
25
- 'consumes' => %w(application/x-www-form-urlencode application/json),
26
- 'produces' => %w(application/json)
27
- )
29
+ Lurker::Json::Schema.new(DEFAULT_SCHEMA.merge(name: service_filename), uri: service_path)
28
30
  end
29
31
  end
30
32
 
@@ -41,7 +43,7 @@ class Lurker::Service
41
43
  end
42
44
 
43
45
  def persist!
44
- Lurker::Json::Writter.write(schema, service_path) unless File.exist?(service_path)
46
+ Lurker::Json::Writer.write(schema, service_path) unless File.exist?(service_path)
45
47
  @opened_endpoints.each { |ep| ep.persist! if ep.respond_to?(:persist!) }
46
48
  end
47
49
 
@@ -104,11 +106,11 @@ class Lurker::Service
104
106
  end
105
107
 
106
108
  def description
107
- @schema['description']
109
+ schema['description']
108
110
  end
109
111
 
110
112
  def discussion
111
- @schema['discussion']
113
+ schema['discussion']
112
114
  end
113
115
 
114
116
  def domains
@@ -122,4 +124,8 @@ class Lurker::Service
122
124
  def response_media_types
123
125
  schema['produces']
124
126
  end
127
+
128
+ def documentation
129
+ @documentation ||= schema.documentation
130
+ end
125
131
  end
@@ -0,0 +1 @@
1
+ This is an autogenerated documentation stub. You can edit it in: `<%= config[:path] %>`
@@ -46,7 +46,7 @@
46
46
  buildActionUrl: function(host, template, values) {
47
47
  for (var i = 0; i < values.length; i++) {
48
48
  var placeholder = new RegExp(':' + values[i].label);
49
- template = template.replace(placeholder, values[i].value);
49
+ template = template.replace(placeholder, encodeURIComponent(values[i].value));
50
50
  }
51
51
  return host + template;
52
52
  },
@@ -1,70 +1,67 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
-
4
3
  <head>
5
-
6
- <meta charset="utf-8">
7
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
8
-
9
- <title><%= @title || @service_presenter.title %></title>
10
- <link href="<%= @service_presenter.html_directory %>/application-<%= @service_presenter.options['css'] %>.css" media="all" rel="stylesheet">
11
- <style type="text/css">
12
- @font-face {
13
- font-family: 'FontAwesome';
14
- src: url("<%= @service_presenter.html_directory %>/fonts/fontawesome-webfont.eot?v=4.0.3");
15
- src: url("<%= @service_presenter.html_directory %>/fonts/fontawesome-webfont.eot?#iefix&v=4.0.3") format("embedded-opentype"),
16
- url("<%= @service_presenter.html_directory %>/fonts/fontawesome-webfont.woff?v=4.0.3") format("woff"),
17
- url("<%= @service_presenter.html_directory %>/fonts/fontawesome-webfont.ttf?v=4.0.3") format("truetype"),
18
- url("<%= @service_presenter.html_directory %>/fonts/fontawesome-webfont.svg?v=4.0.3#fontawesomeregular") format("svg");
19
- font-weight: normal;
20
- font-style: normal;
21
- }
22
- </style>
23
-
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title><%= title %></title>
7
+ <link href="<%= @service_presenter.asset_path('application.css') %>" media="all" rel="stylesheet">
8
+ <style type="text/css">
9
+ @font-face {
10
+ font-family: 'FontAwesome';
11
+ src: url("<%= @service_presenter.asset_path '/fonts/fontawesome-webfont.eot?v=4.0.3' %>");
12
+ src: url("<%= @service_presenter.asset_path '/fonts/fontawesome-webfont.eot?#iefix&v=4.0.3' %>") format("embedded-opentype"),
13
+ url("<%= @service_presenter.asset_path '/fonts/fontawesome-webfont.woff?v=4.0.3' %>") format("woff"),
14
+ url("<%= @service_presenter.asset_path '/fonts/fontawesome-webfont.ttf?v=4.0.3' %>") format("truetype"),
15
+ url("<%= @service_presenter.asset_path '/fonts/fontawesome-webfont.svg?v=4.0.3#fontawesomeregular' %>") format("svg");
16
+ font-weight: normal;
17
+ font-style: normal;
18
+ }
19
+ </style>
24
20
  </head>
25
-
26
21
  <body>
27
22
 
28
- <header class="navbar navbar-static-top bs-docs-nav" id="top" role="banner">
29
- <div class="container">
30
- <div class="navbar-header">
31
- <a class="navbar-brand" href="<%= @service_presenter.html_directory %>"><%= @service_presenter.name %></a>
32
- </div>
33
- </div>
34
- </header>
23
+ <header class="navbar navbar-static-top bs-docs-nav" id="top" role="banner">
24
+ <div class="container">
25
+ <div class="navbar-header">
26
+ <a class="navbar-brand" href="<%= @service_presenter.html_directory %>"><%= @service_presenter.name %></a>
27
+ </div>
28
+ </div>
29
+ </header>
35
30
 
36
- <div class="container bs-docs-container">
37
- <div class="row">
38
- <div class="col-md-9" role="main">
39
- <div class="bs-docs-section">
40
- <%= yield %>
41
- </div>
42
- </div>
43
- <div class="col-md-3">
44
- <div class="bs-docs-sidebar hidden-print" role="complementary">
45
- <ul class="nav bs-docs-sidenav">
46
- <%= render 'layouts/sidemenu' %>
47
- </ul>
48
- </div>
49
- </div>
31
+ <div class="container bs-docs-container">
32
+ <div class="row">
33
+ <div class="col-md-9" role="main">
34
+ <div class="bs-docs-section">
35
+ <%= yield %>
50
36
  </div>
51
37
  </div>
52
-
53
- <footer class="bs-docs-footer" role="contentinfo">
54
- <div class="container">
55
- <ul class="bs-docs-footer-links muted">
56
- <li>·</li>
57
- <% if @service_presenter.options[:footer].present? %>
58
- <li><%= @service_presenter.name %>&nbsp;<%= @service_presenter.options[:footer] %></li>
59
- <li>·</li>
60
- <% end %>
61
- <% if @service_presenter.options[:lurker].present? %>
62
- <li><%= @service_presenter.options[:lurker] %></li>
63
- <li>·</li>
64
- <% end %>
38
+ <div class="col-md-3">
39
+ <div class="bs-docs-sidebar hidden-print" role="complementary">
40
+ <ul class="nav bs-docs-sidenav">
41
+ <%= render 'layouts/sidemenu' %>
65
42
  </ul>
66
43
  </div>
67
- </footer>
68
- <script src="<%= @service_presenter.html_directory %>/application-<%= @service_presenter.options['js'] %>.js"></script>
44
+ </div>
45
+ </div>
46
+ </div>
47
+
48
+ <footer class="bs-docs-footer" role="contentinfo">
49
+ <div class="container">
50
+ <ul class="bs-docs-footer-links muted">
51
+ <li>·</li>
52
+ <% if @service_presenter.footer.present? %>
53
+ <li><%= raw @service_presenter.footer %></li>
54
+ <li>·</li>
55
+ <% end %>
56
+ <% if @service_presenter.lurker.present? %>
57
+ <li><%= raw @service_presenter.lurker %></li>
58
+ <li>·</li>
59
+ <% end %>
60
+ </ul>
61
+ </div>
62
+ </footer>
63
+
64
+ <script src="<%= @service_presenter.asset_path 'application.js' %>"></script>
65
+
69
66
  </body>
70
67
  </html>