lurker 0.6.8 → 1.0.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 (82) hide show
  1. checksums.yaml +5 -5
  2. data/.hound.yml +4 -78
  3. data/.jshintrc +33 -0
  4. data/.rspec +1 -2
  5. data/.rubocop.yml +0 -1
  6. data/.travis.yml +30 -19
  7. data/Gemfile +0 -33
  8. data/README.md +32 -53
  9. data/Rakefile +3 -3
  10. data/cucumber.yml +1 -2
  11. data/features/atom_persistent_within_the_same_type.feature +4 -4
  12. data/features/controller_nested_schema_scaffolding.feature +7 -10
  13. data/features/controller_schema_scaffolding.feature +1 -3
  14. data/features/dereferencing_through_inlining.feature +1 -3
  15. data/features/html_generation.feature +26 -4
  16. data/features/minitest.feature +3 -8
  17. data/features/multidomain_support.feature +6 -10
  18. data/features/multitype_request_support.feature +1 -3
  19. data/features/partials.feature +3 -8
  20. data/features/request_nested_schema_scaffolding.feature +0 -2
  21. data/features/request_schema_scaffolding.feature +0 -2
  22. data/features/schema_suffixes.feature +2 -18
  23. data/features/schema_updating_within_test_suite.feature +2 -6
  24. data/features/step_definitions/additional_cli_steps.rb +16 -12
  25. data/features/support/env.rb +50 -10
  26. data/features/test_endpoint.feature +2 -9
  27. data/gemfiles/rails_4.gemfile +14 -0
  28. data/gemfiles/rails_5.gemfile +10 -0
  29. data/gemfiles/rails_6.gemfile +10 -0
  30. data/lib/lurker.rb +9 -2
  31. data/lib/lurker/cli.rb +148 -128
  32. data/lib/lurker/endpoint.rb +11 -7
  33. data/lib/lurker/form_builder.rb +22 -31
  34. data/lib/lurker/json/concerns/validatable.rb +5 -1
  35. data/lib/lurker/json/parser.rb +1 -1
  36. data/lib/lurker/json/schema.rb +19 -6
  37. data/lib/lurker/json/{writter.rb → writer.rb} +2 -2
  38. data/lib/lurker/presenters/base_presenter.rb +10 -34
  39. data/lib/lurker/presenters/endpoint_presenter.rb +19 -8
  40. data/lib/lurker/presenters/schema_presenter.rb +6 -5
  41. data/lib/lurker/presenters/service_presenter.rb +41 -7
  42. data/lib/lurker/rendering_controller.rb +14 -7
  43. data/lib/lurker/service.rb +27 -11
  44. data/lib/lurker/spec_helper/rspec.rb +0 -4
  45. data/lib/lurker/spy.rb +3 -1
  46. data/lib/lurker/templates/documentation.md.tt +1 -0
  47. data/lib/lurker/templates/javascripts/lurker.js +133 -91
  48. data/lib/lurker/templates/layouts/_sidemenu.html.erb +2 -2
  49. data/lib/lurker/templates/layouts/application.html.erb +54 -57
  50. data/lib/lurker/templates/layouts/print.html.erb +31 -0
  51. data/lib/lurker/templates/lurker/rendering/_endpoint.html.erb +37 -0
  52. data/lib/lurker/templates/lurker/rendering/_param_form_element.html.erb +1 -1
  53. data/lib/lurker/templates/lurker/rendering/_service.html.erb +7 -0
  54. data/lib/lurker/templates/lurker/rendering/_submit_form.html.erb +77 -73
  55. data/lib/lurker/templates/lurker/rendering/all.html.erb +5 -0
  56. data/lib/lurker/templates/lurker/rendering/index.html.erb +1 -10
  57. data/lib/lurker/templates/lurker/rendering/show.html.erb +1 -37
  58. data/lib/lurker/templates/public/application.css +6 -2
  59. data/lib/lurker/templates/public/application.js +13 -13
  60. data/lib/lurker/templates/stylesheets/application.scss +3 -0
  61. data/lib/lurker/version.rb +1 -1
  62. data/lurker.gemspec +31 -33
  63. data/spec/spec_helper.rb +0 -1
  64. data/tasks/build.rake +12 -8
  65. data/tasks/generate.rake +44 -17
  66. data/templates/Dockerfile +26 -0
  67. data/templates/generate_stuff.rb +59 -26
  68. data/templates/lurker_app.rb +27 -48
  69. data/templates/rails4_ruby26_thread_error_fix.rb +20 -0
  70. metadata +149 -106
  71. checksums.yaml.gz.sig +0 -2
  72. data.tar.gz.sig +0 -3
  73. data/Appraisals +0 -20
  74. data/gemfiles/rails_32.gemfile +0 -27
  75. data/gemfiles/rails_40.gemfile +0 -27
  76. data/gemfiles/rails_41.gemfile +0 -27
  77. data/gemfiles/rails_42.gemfile +0 -27
  78. data/lib/lurker/templates/lurker/rendering/_param_form_legend.html.erb +0 -1
  79. data/lib/lurker/templates/meta_service.md.erb +0 -20
  80. data/lib/lurker/validation_error.rb +0 -4
  81. data/templates/rails32_http_patch_support.rb +0 -125
  82. metadata.gz.sig +0 -0
@@ -6,11 +6,19 @@ SimpleCov.start do
6
6
  end
7
7
  end
8
8
 
9
+ def relative_example_path
10
+ if rails_version = ENV['BUNDLE_GEMFILE'].to_s.match(/rails_\d+/)
11
+ "tmp/lurker_app_#{rails_version}"
12
+ else
13
+ raise "Export BUNDLE_GEMFILE=gemfiles/rails... explicitly"
14
+ end
15
+ end
16
+
9
17
  def example_path
10
- if rails_version = ENV['BUNDLE_GEMFILE'].to_s.match(/rails_\d\d/)
18
+ if rails_version = ENV['BUNDLE_GEMFILE'].to_s.match(/rails_\d+/)
11
19
  File.expand_path("../../../tmp/lurker_app_#{rails_version}", __FILE__)
12
20
  else
13
- raise "Use `appraisal rails-XY cucumber ...` or export BUNDLE_GEMFILE=gemfiles/... explicitly"
21
+ raise "Export BUNDLE_GEMFILE=gemfiles/rails... explicitly"
14
22
  end
15
23
  end
16
24
 
@@ -23,21 +31,53 @@ World(RSpec::Matchers)
23
31
  require 'capybara'
24
32
  require 'capybara/dsl'
25
33
  require 'capybara/cucumber'
26
- require 'capybara/poltergeist'
34
+ require 'webdrivers/chromedriver'
27
35
  require "#{example_path}/config/environment"
28
36
  require 'database_cleaner'
29
37
  require 'database_cleaner/cucumber'
30
38
 
31
- Capybara.app = Rails.application
32
- Capybara.javascript_driver = :poltergeist
39
+ Capybara.register_driver :chrome do |app|
40
+ Capybara::Selenium::Driver.new(app, browser: :chrome)
41
+ end
33
42
 
43
+ Capybara.register_driver :headless_chrome do |app|
44
+ Selenium::WebDriver.logger.level = :debug if ENV['CAPYBARA_DEBUG'].present?
45
+ browser_capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(loggingPrefs: { browser: 'ALL' })
46
+ browser_options = Selenium::WebDriver::Chrome::Options.new(args: %w[headless disable-gpu no-sandbox disable-dev-shm-usage window-size=1900,1080])
47
+ browser_options.add_argument('--ignore-certificate-errors')
48
+ # Disable w3c mode (default as of Chrome 75) to allow for logging
49
+ browser_options.add_option(:w3c, false)
50
+ Capybara::Selenium::Driver.new app,
51
+ browser: :chrome,
52
+ options: browser_options,
53
+ desired_capabilities: browser_capabilities
54
+ end
55
+
56
+ Capybara.app = Rails.application
57
+ Capybara.server = :puma, { Silent: true, Threads: '1:1' }
58
+ Capybara.javascript_driver = ENV['CAPYBARA_JS_DRIVER']&.to_sym || :headless_chrome
34
59
  DatabaseCleaner.strategy = :truncation
35
60
 
61
+ # otherwise it cleans up all rails folder
62
+ # https://github.com/cucumber/aruba/blob/bf612766ac51e28ca354e735980cd8a5d7eb296f/lib/aruba/setup.rb#L27L31
63
+ # it force deletes the working_directory,
64
+ # but it has to be working_directory to cd in and run `bin/rspec`
65
+ # this forces @no-clobber everywhere
66
+ # use CLEAN=1 env var to clean proper places
67
+ module ArubaSetupNoClobber
68
+ def working_directory(clobber = true)
69
+ super(false)
70
+ end
71
+ end
72
+ Aruba::Setup.prepend(ArubaSetupNoClobber)
73
+
36
74
  # see: https://github.com/colszowka/simplecov/issues/234
37
75
  Aruba.configure do |config|
38
- config.before_cmd do |cmd|
39
- set_env 'SIMPLECOV_CMDNAME', Digest::MD5.hexdigest(cmd)
40
- set_env 'SIMPLECOV_ROOT', File.expand_path('../../..', __FILE__)
76
+ config.working_directory = relative_example_path # Aruba::Contracts::RelativePath
77
+ config.activate_announcer_on_command_failure = [:stdout]
78
+ config.before :command do |cmd|
79
+ set_environment_variable 'SIMPLECOV_CMDNAME', Digest::MD5.hexdigest(cmd.object_id.to_s)
80
+ set_environment_variable 'SIMPLECOV_ROOT', File.expand_path('../../..', __FILE__)
41
81
  end
42
82
  end
43
83
 
@@ -47,8 +87,8 @@ Before do
47
87
  DatabaseCleaner.start
48
88
  if ENV['CLEAN']
49
89
  system "bin/spring stop"
50
- %w[lurker html public/lurker spec/requests spec/controllers].each do |dir_name|
51
- in_current_dir { _rm_rf(dir_name) }
90
+ %w[lurker public/lurker spec/requests spec/controllers].each do |dir_name|
91
+ in_current_directory { remove(dir_name, force: true) }
52
92
  end
53
93
  end
54
94
  end
@@ -17,9 +17,6 @@ Feature: test endpoint
17
17
  description: 'user updating'
18
18
  requestParameters:
19
19
  properties:
20
- id:
21
- type: integer
22
- example: 1
23
20
  user:
24
21
  type: object
25
22
  properties:
@@ -56,8 +53,6 @@ Feature: test endpoint
56
53
  Scenario: json schema tests request and response using "users/update"
57
54
  Given a file named "spec/controllers/api/v1/users_controller_spec.rb" with:
58
55
  """ruby
59
- require "spec_helper"
60
-
61
56
  describe Api::V1::UsersController, :lurker do
62
57
  render_views
63
58
 
@@ -66,7 +61,7 @@ Feature: test endpoint
66
61
  end
67
62
 
68
63
  it "updates a user" do
69
- patch :update, id: user.id, user: { name: 'Bob' }
64
+ patch :update, params: { id: user.id, user: { name: 'Bob' } }
70
65
  expect(response).to be_success
71
66
  end
72
67
  end
@@ -78,8 +73,6 @@ Feature: test endpoint
78
73
  Scenario: json schema tests response parameters and tell what fails using "users/update"
79
74
  Given a file named "spec/controllers/api/v1/users_controller_blank_spec.rb" with:
80
75
  """ruby
81
- require "spec_helper"
82
-
83
76
  describe Api::V1::UsersController, :lurker do
84
77
  render_views
85
78
 
@@ -88,7 +81,7 @@ Feature: test endpoint
88
81
  end
89
82
 
90
83
  it "updates a user" do
91
- patch :update, id: user.id, user: { name: '' }, format: 'json'
84
+ patch :update, params: { id: user.id, user: { name: '' }, format: 'json' }
92
85
  expect(response).not_to be_success
93
86
  end
94
87
  end
@@ -0,0 +1,14 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "rails", "~> 4.2"
4
+ gem "bigdecimal", "~> 1.4"
5
+ gem "pg", "<= 0.20" # doesnt use 1.0 by install, 0.21 too many warnings
6
+
7
+ gem "rails-forward_compatible_controller_tests", "> 0"
8
+
9
+ gem "jquery-rails"
10
+ gem "bootstrap-sass"
11
+ gem "remotipart"
12
+ gem "uglifier"
13
+
14
+ gemspec :path => "../"
@@ -0,0 +1,10 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "rails", "~> 5.2"
4
+
5
+ gem "jquery-rails"
6
+ gem "bootstrap-sass"
7
+ gem "remotipart"
8
+ gem "uglifier"
9
+
10
+ gemspec :path => "../"
@@ -0,0 +1,10 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "rails", "~> 6.0"
4
+
5
+ gem "jquery-rails"
6
+ gem "bootstrap-sass"
7
+ gem "remotipart"
8
+ gem "uglifier"
9
+
10
+ gemspec :path => "../"
@@ -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
@@ -52,7 +60,6 @@ require 'lurker/ref_object'
52
60
  require 'lurker/erb_schema_context'
53
61
  require 'lurker/service'
54
62
  require 'lurker/validator'
55
- require 'lurker/validation_error'
56
63
  require 'lurker/utils'
57
64
  require 'lurker/endpoint'
58
65
  require 'lurker/rendering_controller'
@@ -65,7 +72,7 @@ require 'lurker/presenters/schema_presenter'
65
72
  require 'lurker/presenters/response_code_presenter'
66
73
  require 'lurker/json'
67
74
  require 'lurker/json/reader'
68
- require 'lurker/json/writter'
75
+ require 'lurker/json/writer'
69
76
  require 'lurker/json/orderer'
70
77
  require 'lurker/json/parser'
71
78
  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,130 @@ 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
+ 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
+ print_html = service_presenter.to_print
84
+ create_file "#{service_presenter.url_name}_print.html", print_html, force: true
85
+
86
+ kit = PDFKit.new(print_html)
87
+ kit.stylesheets << assets['application.css']
88
+ create_file "#{service_presenter.url_name}.pdf", kit.to_pdf, force: true
75
89
  end
76
90
 
77
91
  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)
92
+ create_file 'index.html', service_presenter.to_html, force: true
95
93
 
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
102
-
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/, '')
94
+ service_presenter.endpoints.each do |endpoint_prefix_group|
95
+ endpoint_prefix_group.each do |endpoint_presenter|
96
+ create_file(endpoint_presenter.relative_path, endpoint_presenter.to_html, force: true)
112
97
  end
113
98
  end
114
99
  end
115
100
 
116
- def output_path
117
- "#{output_prefix}/#{url_base_path}"
101
+ def setup_schema_root!(path)
102
+ Lurker.service_path = File.expand_path(path)
103
+ raise Lurker::NotFound.new(Lurker.service_path) unless Lurker.valid_service_path?
104
+ say_status :using, path
118
105
  end
119
106
 
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"
107
+ def setup_rendering_engine!
108
+ I18n.config.enforce_available_locales = true
109
+ Lurker::RenderingController.prepend_view_path Lurker::Cli.templates_root
110
+ if options[:templates].present?
111
+ Lurker::RenderingController.prepend_view_path Pathname.new(options[:templates]).expand_path
127
112
  end
113
+ Lurker::RenderingController.config.assets_dir = assets_root
128
114
  end
129
115
 
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
116
+ def prepare_assets!
117
+ directory assets_root, '.', exclude_pattern: /application\.(js|css)$/
118
+ digest_asset!('application.js')
119
+ digest_asset!('application.css')
137
120
  end
138
121
 
139
- def has_valid_origin?
140
- origin.directory?
122
+ def cleanup_assets!
123
+ actual = assets.values
124
+ Dir.glob('*.{js,css,gz}').each do |fname|
125
+ remove_file fname unless actual.include? fname.sub(/\.gz/, '')
126
+ end
141
127
  end
142
128
 
143
- def service_presenters
144
- @service_presenters ||= services.map do |service|
145
- Lurker::ServicePresenter.new(service, html_options, &filtering_block)
129
+ def digest_asset!(name)
130
+ if (asset_path = assets_root + name).exist?
131
+ digest_path = asset_digest_path(asset_path).basename
132
+ assets[asset_path.basename.to_s] = digest_path.to_s
133
+ copy_file asset_path, digest_path, skip: true
134
+ spawn "cat #{digest_path} | gzip -9 > #{digest_path}.gz"
146
135
  end
147
136
  end
148
137
 
138
+ def service_presenter
139
+ @service_presenter ||= Lurker::ServicePresenter.new(Lurker.service, html_options, &filtering_block)
140
+ end
141
+
149
142
  def filtering_block
150
143
  if options['select'].present?
151
144
  select = /#{options['select']}/
@@ -167,29 +160,75 @@ module Lurker
167
160
 
168
161
  def html_options
169
162
  @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
163
+ static_html: true,
164
+ url_base_path: url_base_path.prepend('/'),
165
+ assets_directory: assets_root,
166
+ assets: assets,
167
+ html_directory: output_path,
168
+ footer: footer,
169
+ lurker: gem_info
177
170
  }
178
171
  end
179
172
  end
180
173
 
181
174
  private
182
175
 
176
+ def output_path
177
+ "#{output_prefix}/#{url_base_path}"
178
+ end
179
+
180
+ def output_prefix
181
+ if explicit = options[:output]
182
+ explicit.sub(/\/?#{url_base_path}\/?$/, '')
183
+ elsif File.exists? 'public'
184
+ 'public'
185
+ else
186
+ raise 'Please, run it from `Rails.root` or pass `-o` option'
187
+ end
188
+ end
189
+
183
190
  def url_base_path
184
191
  options[:url_base_path].presence.try(:strip).try(:sub, /^\/+/, '') || Lurker::DEFAULT_URL_BASE
185
192
  end
186
193
 
194
+ def assets
195
+ @assets ||= {}
196
+ end
197
+
198
+ def assets_root
199
+ Lurker::Cli.assets_root
200
+ end
201
+
202
+ def asset_logical_path(path)
203
+ path = Pathname.new(path) unless path.is_a? Pathname
204
+ path.sub %r{-[0-9a-f]{40}\.}, '.'
205
+ end
206
+
207
+ def asset_digest_path(path)
208
+ path = Pathname.new(path) unless path.is_a? Pathname
209
+ asset_logical_path(path).sub(/\.(\w+)$/) { |ext| "-#{hexdigest(path)}#{ext}" }
210
+ end
211
+
212
+ def hexdigest(path)
213
+ Digest::SHA1.hexdigest(open(path).read)
214
+ end
215
+
216
+ def path_extnames(path)
217
+ File.basename(path).scan(/\.[^.]+/)
218
+ end
219
+
220
+ def footer
221
+ `git rev-parse --short HEAD`.to_s.strip
222
+ rescue
223
+ ''
224
+ end
225
+
187
226
  def gem_info
188
227
  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
228
+ Bundler.locked_gems.specs.select { |s| s.name == 'lurker' }.first # 1.6
229
+ else
230
+ Bundler.definition.sources.detect { |s| s.specs.map(&:name).include?('lurker') } # 1.3
231
+ end
193
232
 
194
233
  if spec.source.respond_to? :revision, true # bundler 1.3 private
195
234
  "#{spec.name} (#{spec.source.send(:revision)})"
@@ -198,26 +237,7 @@ module Lurker
198
237
  end
199
238
  rescue => e
200
239
  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)
240
+ 'lurker (unknown)'
221
241
  end
222
242
  end
223
243
  end