bookbindery 9.4.2 → 9.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: aa865c7b991f92f4fa15398088468c1ccde53178
4
- data.tar.gz: 6bcee44842644b0da4edabe3ebd061073c324242
3
+ metadata.gz: a7fb273894d32de11b696ffd383b8d55ded9b612
4
+ data.tar.gz: 916e689fdca4e2386643bfe17b85fce557fb46df
5
5
  SHA512:
6
- metadata.gz: 4a4c3941bd7ee1e34842824cc961be50789a9c1f914fb24f945fad96745cff027836d8d8a97c962933fc590e5d2607b6237b4006533be5b9741f36bcf7b66ca8
7
- data.tar.gz: a21bef58bb16babc0584ee099a728b2f4648dd23061ebc6963da1536280afca982b3e65e29c5c596b1f3b5904897584882f517abd919803c34006ad9bde4def6
6
+ metadata.gz: 4b2e0f90300f0ac55df5d5c48945a03b7249a07fdc4f4723d5e005ef1af611814490b64117a95aea9d5fdab925bced0f9c94d338ec841d6658dbbd88e6e67b5d
7
+ data.tar.gz: 534dbb03ae216b40205e25e9fc4495f23dda3ab6d90fb3e36201ac25b9c9e57a20d976741e5dd226ff9061bc483426050bfe05bd6148350520a31d09913ce59a
@@ -2,7 +2,7 @@ require 'base64'
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'bookbindery'
5
- s.version = '9.4.2'
5
+ s.version = '9.5.0'
6
6
  s.summary = 'Markdown to Rackup application documentation generator'
7
7
  s.description = 'A command line utility to be run in Book repositories to stitch together their constituent Markdown repos into a static-HTML-serving application'
8
8
  s.authors = ['Mike Grafton', 'Lucas Marks', 'Gavin Morgan', 'Nikhil Gajwani', 'Dan Wendorf', 'Brenda Chan', 'Matthew Boedicker', 'Andrew Bruce', 'Frank Kotsianas', 'Elena Sharma', 'Christa Hartsock', 'Michael Trestman', 'Alpha Chen', 'Sarah McAlear', 'Gregg Van Hove']
@@ -65,13 +65,7 @@ module Bookbinder
65
65
 
66
66
  def product_info
67
67
  return '' if config['product_info'].nil?
68
- {'use_local_header' => config['product_info']['use_local_header'],
69
- 'latest_stable_version' => config['product_info']['latest_stable_version'],
70
- 'changelog_href' => config['product_info']['changelog_href'],
71
- 'local_header_img' => config['product_info']['local_header_img'],
72
- 'local_header_title' => config['product_info']['local_header_title'],
73
- 'local_header_links' => config['product_info']['local_header_links'],
74
- 'local_header_version_list' => config['product_info']['local_header_version_list']}
68
+ config['product_info']
75
69
  end
76
70
 
77
71
  private
@@ -21,9 +21,15 @@ module Bookbinder
21
21
 
22
22
  root = absolute_source_from_path(Pathname(config.subnav_root))
23
23
 
24
- raise SubnavRootMissingError.new('Subnav root not found at: ' + config.subnav_root) if root.nil?
24
+ if root.nil?
25
+ if @require_valid_subnav_links
26
+ raise SubnavRootMissingError.new('Subnav root not found at: ' + config.subnav_root)
27
+ else
28
+ return {links: []}.to_json
29
+ end
30
+ end
25
31
 
26
- @parsed_files = { Pathname(root) => '(root)'}
32
+ @parsed_files = {Pathname(root) => '(root)'}
27
33
 
28
34
  {links: gather_urls_and_texts(root)}.to_json
29
35
  end
@@ -54,14 +60,24 @@ module Bookbinder
54
60
  next_source = absolute_source_from_path(expanded_href)
55
61
  nested_links = {}
56
62
 
57
- if @require_valid_subnav_links
58
- raise SubnavBrokenLinkError.new(<<-ERROR) unless next_source
59
- Broken link found in subnav for product_id: #{config.id}
63
+ no_children = false
64
+ no_children ||= validate_no_broken_link(expanded_href, next_source, source)
65
+ no_children ||= validate_no_duplicate_link(expanded_href, next_source, source)
60
66
 
61
- Link: #{expanded_href}
62
- Source file: #{source}
63
- ERROR
64
- raise SubnavDuplicateLinkError.new(<<-ERROR) if @parsed_files.has_key?(next_source)
67
+ unless no_children
68
+ @parsed_files[next_source] = source
69
+ nested_urls_and_texts = gather_urls_and_texts(next_source)
70
+ nested_links.merge!(nestedLinks: nested_urls_and_texts) unless nested_urls_and_texts.empty?
71
+ end
72
+
73
+ {url: '/' + expanded_href.to_s, text: element.inner_text}.merge(nested_links)
74
+ end
75
+ end
76
+
77
+ def validate_no_duplicate_link(expanded_href, next_source, source)
78
+ if @parsed_files.has_key?(next_source)
79
+ if @require_valid_subnav_links
80
+ raise SubnavDuplicateLinkError.new(<<-ERROR)
65
81
  )
66
82
  Duplicate link found in subnav for product_id: #{config.id}
67
83
 
@@ -69,14 +85,27 @@ Link: #{expanded_href}
69
85
  Original file: #{@parsed_files[next_source]}
70
86
  Current file: #{source}
71
87
  ERROR
72
-
73
- @parsed_files[next_source] = source
74
- nested_urls_and_texts = gather_urls_and_texts(next_source)
75
- nested_links.merge!(nestedLinks: nested_urls_and_texts) unless nested_urls_and_texts.empty?
88
+ else
89
+ no_children = true
76
90
  end
91
+ end
92
+ no_children
93
+ end
77
94
 
78
- {url: '/' + expanded_href.to_s, text: element.inner_text}.merge(nested_links)
95
+ def validate_no_broken_link(expanded_href, next_source, source)
96
+ unless next_source
97
+ if @require_valid_subnav_links
98
+ raise SubnavBrokenLinkError.new(<<-ERROR)
99
+ Broken link found in subnav for product_id: #{config.id}
100
+
101
+ Link: #{expanded_href}
102
+ Source file: #{source}
103
+ ERROR
104
+ else
105
+ no_children = true
106
+ end
79
107
  end
108
+ no_children
80
109
  end
81
110
 
82
111
  def nav_items(base_node)
@@ -15,9 +15,10 @@ module Bookbinder
15
15
  end
16
16
 
17
17
  def call(request_env)
18
- results = query.search(extract_query_params(request_env['QUERY_STRING']))
18
+ query = Query.new(extract_query_params(request_env['QUERY_STRING']))
19
+ query.get_results(client_class.new(url: elasticsearch_url))
19
20
 
20
- [200, {'Content-Type' => 'text/html'}, [renderer.render_results(results)]]
21
+ [200, {'Content-Type' => 'text/html'}, [renderer.render_results(query)]]
21
22
  rescue Exception => e
22
23
  puts e.message
23
24
  puts e.backtrace.join("\n")
@@ -41,10 +42,6 @@ module Bookbinder
41
42
  def elasticsearch_url
42
43
  @elasticsearch_url ||= JSON.parse(environment['VCAP_SERVICES'])['searchly'][0]['credentials']['uri']
43
44
  end
44
-
45
- def query
46
- Query.new(client_class.new(url: elasticsearch_url))
47
- end
48
45
  end
49
46
  end
50
47
  end
@@ -1,41 +1,74 @@
1
1
  require 'yaml'
2
2
 
3
- require_relative 'result'
3
+ require_relative 'hit'
4
4
 
5
5
  module Bookbinder
6
6
  module Search
7
7
  class Query
8
- def initialize(client)
9
- @client = client
10
- end
8
+ attr_reader :search_term, :product_name, :product_version, :page_number, :result_list, :result_count, :last_page, :page_window
11
9
 
12
- def search(params)
13
- query = params.fetch('q', '')
10
+ def initialize(params)
11
+ @search_term = params.fetch('q', '')
12
+ @product_name = params.fetch('product_name', nil)
13
+ @product_version = @product_name && params.fetch('product_version', nil)
14
+ @page_number = @search_term == '' ? 1 : [params['page'].to_i, 1].max
15
+ end
14
16
 
15
- return Result.new(query, 0, [], 1) if query == ''
17
+ def query_options
18
+ options = YAML.load_file(File.expand_path('../../../search.yml', __FILE__))
16
19
 
17
- page_number = [params['page'].to_i, 1].max
20
+ options['from'] = (page_number - 1) * 10
21
+ options['query']['bool']['should']['query_string']['query'] = search_term
18
22
 
19
- query_options = YAML.load_file(File.expand_path('../../../search.yml', __FILE__))
23
+ unless product_name.nil?
24
+ filters = [{
25
+ 'term' => { 'product_name' => product_name }
26
+ }]
20
27
 
21
- query_options['from'] = (page_number - 1) * 10
22
- query_options['query']['query_string']['query'] = query
28
+ unless product_version.nil?
29
+ filters << {'term' => { 'product_version' => product_version }}
30
+ end
23
31
 
24
- results = client.search index: 'searching', body: query_options
32
+ options['query']['bool']['filter'] = {
33
+ 'bool' => {
34
+ 'must' => filters
35
+ }
36
+ }
37
+ end
25
38
 
26
- Result.new(
27
- query,
28
- results['hits']['total'],
29
- results['hits']['hits'],
30
- page_number
31
- )
39
+ options
40
+ end
32
41
 
42
+ def get_results(elasticsearch_client)
43
+ if search_term == ''
44
+ @result_count = 0
45
+ @result_list = []
46
+ @last_page = 1
47
+ else
48
+ results = elasticsearch_client.search index: 'searching', body: query_options
49
+ @result_count = results['hits']['total']
50
+ @result_list = results['hits']['hits'].map { |h| Hit.new(h) }
51
+ @last_page = (result_count / 10.0).ceil
52
+ end
53
+ @page_window = calculate_page_window
33
54
  end
34
55
 
35
56
  private
36
57
 
37
- attr_reader :client
58
+ def calculate_page_window
59
+ window_start = [page_number - 2, 1].max
60
+ window_end = [window_start + 4, last_page].min
61
+ window = (window_start .. window_end).to_a
38
62
 
63
+ if window.length < 5 && window.last == last_page && window.first != 1
64
+ window.unshift(window.first - 1)
65
+ if window.length < 5
66
+ window.unshift(window.first - 1)
67
+ end
68
+ end
69
+
70
+ window
71
+ end
39
72
  end
40
73
  end
41
74
  end
@@ -1,17 +1,31 @@
1
1
  <div class="search-results">
2
2
  <form method="get">
3
- <input name="q" value="<%= query %>"/>
3
+
4
+ <% unless product_name.nil? %>
5
+ <h4 style="border: 1px solid #ccc; padding: 4px 20px;">
6
+ Filtering by: <%= product_name %>
7
+ <% unless product_version.nil? %>and <%= product_version %>
8
+ <% end %>
9
+ </h4>
10
+ <% end %>
11
+ <input name="q" value="<%= search_term %>"/>
12
+ <% unless product_name.nil? %>
13
+ <input type="hidden" name="product_name" value="<%= product_name %>"/>
14
+ <% end %>
15
+ <% unless product_version.nil? %>
16
+ <input type="hidden" name="product_version" value="<%= product_version %>"/>
17
+ <% end %>
4
18
  </form>
5
19
 
6
- <% if hit_count == 0 %>
20
+ <% if result_count == 0 %>
7
21
  <div class="no-results">No Results</div>
8
22
  <% else %>
9
23
  <div class="result-summary">
10
- Showing <%= (page_number - 1) * 10 + 1 %> to <%= [(page_number - 1) * 10 + 10, hit_count].min %> of <%= hit_count %> results.
24
+ Showing <%= (page_number - 1) * 10 + 1 %> to <%= [(page_number - 1) * 10 + 10, result_count].min %> of <%= result_count %> results.
11
25
  </div>
12
26
 
13
27
  <ul class="search-results-list">
14
- <% hits.each do |hit| %>
28
+ <% result_list.each do |hit| %>
15
29
  <li>
16
30
  <a href="<%= hit.url %>"><%= hit.title %></a>
17
31
  <div><%= hit.text %></div>
@@ -20,19 +34,22 @@
20
34
  </ul>
21
35
 
22
36
  <div class="pagination">
37
+ <% search_query = "/search?q=#{ search_term }" %>
38
+ <% search_query << "&product_name=#{ product_name }" unless product_name.nil? %>
39
+ <% search_query << "&product_version=#{ product_version }" unless product_version.nil? %>
23
40
  <% if page_number == 1 %>
24
41
  <span class="disabled page first">First</span>
25
42
  <span class="disabled page previous">Prev</span>
26
43
  <% else %>
27
- <a class="page first" href="/search?q=<%= query %>">First</a>
28
- <a class="page previous" href="/search?q=<%= query %>&page=<%= page_number - 1 %>">Prev</a>
44
+ <a class="page first" href="<%= search_query %>">First</a>
45
+ <a class="page previous" href="<%= search_query %>&page=<%= page_number - 1 %>">Prev</a>
29
46
  <% end %>
30
47
 
31
48
  <% page_window.each do |page| %>
32
49
  <% if page == page_number %>
33
50
  <span class="current page"><%= page %></span>
34
51
  <% else %>
35
- <a class="page" href="/search?q=<%= query %>&page=<%= page %>"><%= page %></a>
52
+ <a class="page" href="<%= search_query %>&page=<%= page %>"><%= page %></a>
36
53
  <% end %>
37
54
  <% end %>
38
55
 
@@ -40,8 +57,8 @@
40
57
  <span class="disabled page next">Next</span>
41
58
  <span class="disabled page last">Last</span>
42
59
  <% else %>
43
- <a class="page next" href="/search?q=<%= query %>&page=<%= page_number + 1 %>">Next</a>
44
- <a class="page last" href="/search?q=<%= query %>&page=<%= last_page %>">Last</a>
60
+ <a class="page next" href="<%= search_query %>&page=<%= page_number + 1 %>">Next</a>
61
+ <a class="page last" href="<%= search_query %>&page=<%= last_page %>">Last</a>
45
62
  <% end %>
46
63
  </div>
47
64
  <% end %>
@@ -1,8 +1,11 @@
1
1
  ---
2
2
  query:
3
- query_string:
4
- query: ''
5
- default_field: text
3
+ bool:
4
+ should:
5
+ query_string:
6
+ query: ''
7
+ default_field: text
8
+ minimum_should_match: 1
6
9
  from: 0
7
10
  size: 10
8
11
  _source:
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bookbindery
3
3
  version: !ruby/object:Gem::Version
4
- version: 9.4.2
4
+ version: 9.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Grafton
@@ -22,7 +22,7 @@ authors:
22
22
  autorequire:
23
23
  bindir: install_bin
24
24
  cert_chain: []
25
- date: 2016-05-10 00:00:00.000000000 Z
25
+ date: 2016-05-20 00:00:00.000000000 Z
26
26
  dependencies:
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: fog-aws
@@ -416,7 +416,6 @@ files:
416
416
  - template_app/lib/search/hit.rb
417
417
  - template_app/lib/search/query.rb
418
418
  - template_app/lib/search/renderer.rb
419
- - template_app/lib/search/result.rb
420
419
  - template_app/lib/server.rb
421
420
  - template_app/mail_sender.rb
422
421
  - template_app/rack_app.rb
@@ -1,35 +0,0 @@
1
- require_relative 'hit'
2
-
3
- module Bookbinder
4
- module Search
5
- class Result
6
- def initialize(query, hit_count, raw_hits, page_number)
7
- @query = query
8
- @hit_count = hit_count
9
- @hits = raw_hits.map { |h| Hit.new(h) }
10
- @page_number = page_number
11
- @last_page = (hit_count / 10.0).ceil
12
- @page_window = calculate_page_window
13
- end
14
-
15
- attr_reader :query, :hit_count, :hits, :page_number, :last_page, :page_window
16
-
17
- private
18
-
19
- def calculate_page_window
20
- window_start = [page_number - 2, 1].max
21
- window_end = [window_start + 4, last_page].min
22
- window = (window_start .. window_end).to_a
23
-
24
- if window.length < 5 && window.last == last_page && window.first != 1
25
- window.unshift(window.first - 1)
26
- if window.length < 5
27
- window.unshift(window.first - 1)
28
- end
29
- end
30
-
31
- window
32
- end
33
- end
34
- end
35
- end