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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9643afaa53257cb69053c126c15700b8d763332e
4
- data.tar.gz: 54247852acb557093f2bde400adf1deffc8b6da9
3
+ metadata.gz: fb9c0414b141e2d48b9c7a6d03be6e671a6ad3ed
4
+ data.tar.gz: 777ba4fb742083bfaabeb5c912be901ae51f9bfc
5
5
  SHA512:
6
- metadata.gz: 79d5676e91e53272c072ca3ca2caf5b307cce5f82c299e1e61d6e7d0cfb9369f7ee8547f53607f8d6adf6b530fab63bbdd2099e7a14dfa8f6740dbb561598ca9
7
- data.tar.gz: fababb8b949417a403726a0b8901fde3c48c9b600f3db35fc72e284f07f094af06fdc83627d00485d7fc62cb6b1d90322ba2a8094d44bf87221c05e96de34515
6
+ metadata.gz: ad1be4d40f3a1558527e61d2bce3b22eb9050f8264189b54d5a2346763a86c7559dd0b6c245ec71a5a8a8100f14d62245d30236d227af8ba91e6de0cb5fcf799
7
+ data.tar.gz: cd34824f79c859a1cc27eea9a0d7b9f23af8f58bcfe680037fae0a151c6a49d593f3c0990677cc8d9288d08e0d9e4ca5dba112495039f96b306d33a766f0eee7
@@ -1,2 +1 @@
1
- hs{}�֗�sn{��#Hǥ$�B3��Ը�{8F2�O)���c�����6�� ��OvK���}*1���ߑ�཮u]8W��?L[��S��݌V]�!{}�]��'J�DQ��=��%�J�� ��vD��Ry2g�Ϳ�2��Q`:Uig�Z�3����&5ʸ�=d'�M��T|+�O><�)�]�~d����Ɯ�mx��'�܀�j���l
2
- �������j��ML�l،��x�gy�_��mp0(�
1
+ Ҕ�+Il�$� 0٫#�bA�������j�q����0��������O§�i(����YN/���:��/+�Zm���5/(��d��2Zk1��p�Ùo|J+w�. �[�\����΀fE*�^��bs'����$ݝ�_� u�� ���v6MpfQ�QϞ���d��O��6��!���7������#�q�`˼9����㣸А��5���~�x�<8V�l��5۩�_k�BL��uS���������
data.tar.gz.sig CHANGED
Binary file
data/README.md CHANGED
@@ -92,6 +92,13 @@ The generation of live-documentation is pretty simple:
92
92
 
93
93
  For different document root or serving URL prefix use `-o` and `-u` options accordingly.
94
94
 
95
+ If you want to provide additional documentation for your API (and you probably should),
96
+ you can use separate Markdown files in the schema folder. To generate documentation
97
+ stubs for the current schema:
98
+
99
+ bin/lurker init_docs # generate documentation stubs for the current schema
100
+
101
+
95
102
  Let's run your `rails s` and visit [http://localhost:3000/lurker/](http://localhost:3000/lurker/)
96
103
  (or see [demo][demo_app2] for example)
97
104
 
@@ -217,7 +224,7 @@ This gem is heavily inspired by them. Thanks, @square & @fredwu
217
224
  Also thanks to
218
225
 
219
226
  - [Andrey Deryabin][aderyabin] for advice
220
- - [React.js][reactjs] for two-way binding
227
+ - [React.js][reactjs] for reactive UI
221
228
  - [highlight.js][hljs] for syntax highlighting
222
229
 
223
230
  [aderyabin]: https://twitter.com/aderyabin
@@ -28,6 +28,14 @@ module Lurker
28
28
  @service_path || DEFAULT_SERVICE_PATH
29
29
  end
30
30
 
31
+ def self.valid_service_path?
32
+ Dir.exist? service_path
33
+ end
34
+
35
+ def self.service
36
+ @service ||= Lurker::Service.new(service_path)
37
+ end
38
+
31
39
  def self.decide_success_with(&block)
32
40
  @success_block = block
33
41
  end
@@ -65,7 +73,7 @@ require 'lurker/presenters/schema_presenter'
65
73
  require 'lurker/presenters/response_code_presenter'
66
74
  require 'lurker/json'
67
75
  require 'lurker/json/reader'
68
- require 'lurker/json/writter'
76
+ require 'lurker/json/writer'
69
77
  require 'lurker/json/orderer'
70
78
  require 'lurker/json/parser'
71
79
  require 'lurker/json/parser/expertise'
@@ -5,6 +5,9 @@ require 'lurker'
5
5
  require 'active_support/inflector'
6
6
 
7
7
  module Lurker
8
+ BUNDLED_TEMPLATES_PATH = Pathname.new('../templates').expand_path(__FILE__)
9
+ BUNDLED_ASSETS_PATH = Pathname.new('../templates/public').expand_path(__FILE__)
10
+
8
11
  # A Thor::Error to be thrown when an lurker directory is not found
9
12
  class NotFound < Thor::Error; end
10
13
 
@@ -12,140 +15,124 @@ module Lurker
12
15
  class Cli < Thor
13
16
  include Thor::Actions
14
17
 
15
- attr_accessor :origin_path, :content
18
+ attr_accessor :content
19
+
20
+ def self.templates_root
21
+ options[:template].present? ? Pathname.new(options[:templates]).expand_path : Lurker::BUNDLED_TEMPLATES_PATH
22
+ end
16
23
 
17
- def self.source_root
18
- File.expand_path("../templates", __FILE__)
24
+ def self.assets_root
25
+ options[:assets].present? ? Pathname.new(options[:assets]).expand_path : Lurker::BUNDLED_ASSETS_PATH
19
26
  end
20
27
 
21
- def self.precompiled_static_root
22
- File.expand_path("../templates/public", __FILE__)
28
+ source_root(templates_root)
29
+
30
+ desc 'init_docs [LURKER_PATH]', 'Create documentation stubs for service and endpoints'
31
+
32
+ def init_docs(lurker_path=Lurker::DEFAULT_SERVICE_PATH)
33
+ say_status nil, 'Creating documentation stubs'
34
+
35
+ setup_schema_root! lurker_path
36
+
37
+ schemas = Lurker.service.endpoints.map(&:schema) << Lurker.service.schema
38
+ schemas.each do |schema|
39
+ rel_path = Pathname.new(schema.documentation_uri).relative_path_from(Pathname.getwd)
40
+ template 'documentation.md.tt', schema.documentation_uri, skip: true, path: rel_path
41
+ end
23
42
  end
24
43
 
25
- desc "convert [LURKER_PATH]", "Convert lurker to HTML"
26
- method_option :rails, :type => :boolean, :desc => "Includes Rails environment"
27
- method_option :exclude, :aliases => "-e", :desc => "Select endpoints by given regexp, if NOT matching prefix"
28
- method_option :select, :aliases => "-s", :desc => "Select endpoints by given regexp, matching prefix"
29
- method_option :output, :aliases => "-o", :desc => "Output path", :default => "public"
30
- method_option :url_base_path, :aliases => "-u", :desc => "URL base path", :default => Lurker::DEFAULT_URL_BASE
31
- method_option :format, :aliases => "-f", :desc => "Format in html or pdf, defaults to html", :default => "html"
32
- method_option :templates, :aliases => "-t", :desc => "Template overrides path"
33
- method_option :content, :aliases => "-c", :desc => "Content to be rendered into html-docs main page"
44
+ desc 'convert [LURKER_PATH]', 'Convert lurker to HTML'
45
+ option :rails, type: :boolean, desc: 'Includes Rails environment'
46
+ option :exclude, aliases: '-e', desc: 'Select endpoints by given regexp, if NOT matching prefix'
47
+ option :select, aliases: '-s', desc: 'Select endpoints by given regexp, matching prefix'
48
+ option :output, aliases: '-o', desc: 'Output path', default: 'public'
49
+ option :url_base_path, aliases: '-u', desc: 'URL base path', default: Lurker::DEFAULT_URL_BASE
50
+ option :templates, aliases: '-t', desc: 'Template overrides path'
51
+ option :assets, aliases: '-a', desc: 'Assets overrides path'
52
+ option :format, aliases: '-f', desc: 'Format in html or pdf, defaults to html', default: 'html'
53
+ option :content, aliases: '-c', desc: 'Content to be rendered into html-docs main page'
54
+
34
55
  def convert(lurker_path=Lurker::DEFAULT_SERVICE_PATH)
35
56
  say_status nil, "Converting lurker to #{options[:format]}"
36
57
 
37
- self.content = get_content(options[:content])
38
- self.origin_path = File.expand_path(lurker_path)
39
- raise Lurker::NotFound.new(origin_path) unless has_valid_origin?
40
- say_status :using, lurker_path
41
-
42
- FileUtils.mkdir_p(output_path)
43
- say_status :inside, output_path
58
+ setup_schema_root! lurker_path
59
+ require "#{Dir.pwd}/config/environment" if options[:rails]
44
60
 
45
- if options[:rails]
46
- require "#{Dir.pwd}/config/environment"
61
+ # for backward compatibility
62
+ if options[:content]
63
+ Lurker.service.documentation = open(File.expand_path(options[:content])).read
47
64
  end
48
65
 
49
- if options[:format] == 'pdf'
50
- convert_to_pdf
51
- else
52
- convert_to_html
66
+ setup_rendering_engine!
67
+
68
+ inside(output_path) do
69
+ say_status :inside, output_path
70
+ prepare_assets!
71
+ if options[:format] == 'pdf'
72
+ convert_to_pdf
73
+ else
74
+ convert_to_html
75
+ end
76
+ cleanup_assets!
53
77
  end
54
78
  end
55
79
 
56
80
  no_tasks do
57
81
  def convert_to_pdf
58
82
  Lurker.safe_require('pdfkit')
59
- css = File.expand_path('application.css', self.class.precompiled_static_root)
60
- inside(output_path) do
61
- service_presenters.each do |service_presenter|
62
- html = "<html><body>"
63
- service_presenter.endpoints.each do |endpoint_prefix_group|
64
- endpoint_prefix_group.each do |endpoint_presenter|
65
- html << endpoint_presenter.to_html(layout: false)
66
- end
67
- end
68
- html << "</body></html>"
69
- kit = PDFKit.new(html, :page_size => 'Letter')
70
- kit.stylesheets << css
71
- url_name = ActiveSupport::Inflector.parameterize(service_presenter.name, '_')
72
- create_file("#{url_name}.pdf", kit.to_pdf, force: true)
73
- end
74
- end
83
+ kit = PDFKit.new(service_presenter.to_print)
84
+ kit.stylesheets << assets['application.css']
85
+ create_file "#{service_presenter.url_name}.pdf", kit.to_pdf, force: true
75
86
  end
76
87
 
77
88
  def convert_to_html
78
- inside(output_path) do
79
- # js, css, fonts
80
- static = []
81
- Dir["#{self.class.precompiled_static_root}/*"].each do |fname|
82
- if match = fname.match(/application\.(js|css)$/)
83
- sha1 = Digest::SHA1.hexdigest(open(fname).read)
84
- html_options.merge! match[1] => sha1
85
- static << (new_name = "application-#{sha1}.#{match[1]}")
86
- FileUtils.cp_r fname, new_name
87
- spawn "cat #{new_name} | gzip -9 > #{new_name}.gz"
88
- else
89
- FileUtils.cp_r fname, Pathname.new(fname).basename.to_s
90
- end
91
- end
92
-
93
- service_presenters.each do |service_presenter|
94
- create_file("index.html", service_presenter.to_html, force: true)
95
-
96
- service_presenter.endpoints.each do |endpoint_prefix_group|
97
- endpoint_prefix_group.each do |endpoint_presenter|
98
- create_file(endpoint_presenter.relative_path, endpoint_presenter.to_html, force: true)
99
- end
100
- end
101
- end
89
+ create_file 'index.html', service_presenter.to_html, force: true
102
90
 
103
- # cleanup
104
- Dir.glob("*.js").each do |fname|
105
- FileUtils.rm fname unless static.include? fname
106
- end
107
- Dir.glob("*.css").each do |fname|
108
- FileUtils.rm fname unless static.include? fname
109
- end
110
- Dir.glob("*.gz").each do |fname|
111
- FileUtils.rm fname unless static.include? fname.sub(/\.gz/, '')
91
+ service_presenter.endpoints.each do |endpoint_prefix_group|
92
+ endpoint_prefix_group.each do |endpoint_presenter|
93
+ create_file(endpoint_presenter.relative_path, endpoint_presenter.to_html, force: true)
112
94
  end
113
95
  end
114
96
  end
115
97
 
116
- def output_path
117
- "#{output_prefix}/#{url_base_path}"
98
+ def setup_schema_root!(path)
99
+ Lurker.service_path = File.expand_path(path)
100
+ raise Lurker::NotFound.new(Lurker.service_path) unless Lurker.valid_service_path?
101
+ say_status :using, path
118
102
  end
119
103
 
120
- def output_prefix
121
- if explicit = options[:output]
122
- explicit.sub(/\/?#{url_base_path}\/?$/, '')
123
- elsif File.exists? "public"
124
- "public"
125
- else
126
- raise "Please, run it from `Rails.root` or pass `-o` option"
127
- end
104
+ def setup_rendering_engine!
105
+ I18n.config.enforce_available_locales = true
106
+ Lurker::RenderingController.prepend_view_path templates_root
107
+ Lurker::RenderingController.config.assets_dir = assets_root
128
108
  end
129
109
 
130
- def template_path
131
- @template_path ||=
132
- if options[:templates]
133
- File.expand_path(options[:templates])
134
- else
135
- File.expand_path("../templates", origin_path)
136
- end
110
+ def prepare_assets!
111
+ directory assets_root, '.', exclude_pattern: /application\.(js|css)$/
112
+ digest_asset!('application.js')
113
+ digest_asset!('application.css')
137
114
  end
138
115
 
139
- def has_valid_origin?
140
- origin.directory?
116
+ def cleanup_assets!
117
+ actual = assets.values
118
+ Dir.glob('*.{js,css,gz}').each do |fname|
119
+ remove_file fname unless actual.include? fname.sub(/\.gz/, '')
120
+ end
141
121
  end
142
122
 
143
- def service_presenters
144
- @service_presenters ||= services.map do |service|
145
- Lurker::ServicePresenter.new(service, html_options, &filtering_block)
123
+ def digest_asset!(name)
124
+ if (asset_path = assets_root + name).exist?
125
+ digest_path = asset_digest_path(asset_path).basename
126
+ assets[asset_path.basename.to_s] = digest_path.to_s
127
+ copy_file asset_path, digest_path, skip: true
128
+ spawn "cat #{digest_path} | gzip -9 > #{digest_path}.gz"
146
129
  end
147
130
  end
148
131
 
132
+ def service_presenter
133
+ @service_presenter ||= Lurker::ServicePresenter.new(Lurker.service, html_options, &filtering_block)
134
+ end
135
+
149
136
  def filtering_block
150
137
  if options['select'].present?
151
138
  select = /#{options['select']}/
@@ -167,29 +154,80 @@ module Lurker
167
154
 
168
155
  def html_options
169
156
  @html_options ||= {
170
- :static_html => true,
171
- :url_base_path => url_base_path.prepend('/'),
172
- :template_directory => template_path,
173
- :html_directory => output_path,
174
- :content => self.content,
175
- :footer => (`git rev-parse --short HEAD`.to_s.strip rescue ""),
176
- :lurker => gem_info
157
+ static_html: true,
158
+ url_base_path: url_base_path.prepend('/'),
159
+ template_directory: templates_root,
160
+ assets_directory: assets_root,
161
+ assets: assets,
162
+ html_directory: output_path,
163
+ footer: footer,
164
+ lurker: gem_info
177
165
  }
178
166
  end
179
167
  end
180
168
 
181
169
  private
182
170
 
171
+ def output_path
172
+ "#{output_prefix}/#{url_base_path}"
173
+ end
174
+
175
+ def output_prefix
176
+ if explicit = options[:output]
177
+ explicit.sub(/\/?#{url_base_path}\/?$/, '')
178
+ elsif File.exists? 'public'
179
+ 'public'
180
+ else
181
+ raise 'Please, run it from `Rails.root` or pass `-o` option'
182
+ end
183
+ end
184
+
183
185
  def url_base_path
184
186
  options[:url_base_path].presence.try(:strip).try(:sub, /^\/+/, '') || Lurker::DEFAULT_URL_BASE
185
187
  end
186
188
 
189
+ def assets
190
+ @assets ||= {}
191
+ end
192
+
193
+ def assets_root
194
+ Lurker::Cli.assets_root
195
+ end
196
+
197
+ def templates_root
198
+ Lurker::Cli.templates_root
199
+ end
200
+
201
+ def asset_logical_path(path)
202
+ path = Pathname.new(path) unless path.is_a? Pathname
203
+ path.sub %r{-[0-9a-f]{40}\.}, '.'
204
+ end
205
+
206
+ def asset_digest_path(path)
207
+ path = Pathname.new(path) unless path.is_a? Pathname
208
+ asset_logical_path(path).sub(/\.(\w+)$/) { |ext| "-#{hexdigest(path)}#{ext}" }
209
+ end
210
+
211
+ def hexdigest(path)
212
+ Digest::SHA1.hexdigest(open(path).read)
213
+ end
214
+
215
+ def path_extnames(path)
216
+ File.basename(path).scan(/\.[^.]+/)
217
+ end
218
+
219
+ def footer
220
+ `git rev-parse --short HEAD`.to_s.strip
221
+ rescue
222
+ ''
223
+ end
224
+
187
225
  def gem_info
188
226
  spec = if Bundler.respond_to? :locked_gems
189
- Bundler.locked_gems.specs.select { |s| s.name == 'lurker' } .first # 1.6
190
- else
191
- Bundler.definition.sources.detect { |s| s.specs.map(&:name).include?('lurker') } # 1.3
192
- end
227
+ Bundler.locked_gems.specs.select { |s| s.name == 'lurker' }.first # 1.6
228
+ else
229
+ Bundler.definition.sources.detect { |s| s.specs.map(&:name).include?('lurker') } # 1.3
230
+ end
193
231
 
194
232
  if spec.source.respond_to? :revision, true # bundler 1.3 private
195
233
  "#{spec.name} (#{spec.source.send(:revision)})"
@@ -198,26 +236,7 @@ module Lurker
198
236
  end
199
237
  rescue => e
200
238
  puts e
201
- "lurker (unknown)"
202
- end
203
-
204
- def get_content(content_fname)
205
- return unless content_fname
206
- content_fname = File.expand_path(content_fname)
207
- if content_fname.ends_with? 'md'
208
- Lurker.safe_require('kramdown')
209
- Kramdown::Document.new(open(content_fname).read).to_html
210
- else
211
- ''
212
- end
213
- end
214
-
215
- def services
216
- @services ||= [Lurker::Service.new(origin_path)]
217
- end
218
-
219
- def origin
220
- Pathname.new(origin_path)
239
+ 'lurker (unknown)'
221
240
  end
222
241
  end
223
242
  end
@@ -19,7 +19,7 @@ module Lurker
19
19
  RESPONSE_CODES = 'responseCodes'.freeze
20
20
  REQUEST_PARAMETERS = 'requestParameters'.freeze
21
21
  RESPONSE_PARAMETERS = 'responseParameters'.freeze
22
- DESCRPTIONS = {
22
+ DESCRIPTIONS = {
23
23
  'index' => 'listing',
24
24
  'show' => '',
25
25
  'edit' => 'editing',
@@ -44,7 +44,7 @@ module Lurker
44
44
  finalize_schema!
45
45
 
46
46
  Lurker::Json::Orderer.reorder(schema) unless persisted?
47
- Lurker::Json::Writter.write(schema, endpoint_path)
47
+ Lurker::Json::Writer.write(schema, endpoint_path)
48
48
 
49
49
  @persisted = true
50
50
  end
@@ -131,6 +131,10 @@ module Lurker
131
131
  @schema[RESPONSE_CODES]
132
132
  end
133
133
 
134
+ def documentation
135
+ @schema.documentation
136
+ end
137
+
134
138
  protected
135
139
 
136
140
  def persisted?
@@ -167,7 +171,7 @@ module Lurker
167
171
  def finalize_schema!
168
172
  path_params = schema[EXTENSIONS][PATH_PARAMS] || {}
169
173
  subject = path_params[CONTROLLER].to_s.split(/\//).last.to_s
170
- description = DESCRPTIONS[path_params[ACTION]]
174
+ description = DESCRIPTIONS[path_params[ACTION]]
171
175
 
172
176
  schema[DESCRIPTION] = "#{subject.singularize} #{description}".strip if schema[DESCRIPTION].blank?
173
177
  schema[PREFIX] = "#{subject} management" if schema[PREFIX].blank?