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 +4 -4
- data/bookbinder.gemspec +1 -1
- data/lib/bookbinder/config/section_config.rb +1 -7
- data/lib/bookbinder/subnav/json_from_markdown_toc.rb +43 -14
- data/template_app/lib/search/handler.rb +3 -6
- data/template_app/lib/search/query.rb +52 -19
- data/template_app/search-results.html.erb +26 -9
- data/template_app/search.yml +6 -3
- metadata +2 -3
- data/template_app/lib/search/result.rb +0 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a7fb273894d32de11b696ffd383b8d55ded9b612
|
4
|
+
data.tar.gz: 916e689fdca4e2386643bfe17b85fce557fb46df
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4b2e0f90300f0ac55df5d5c48945a03b7249a07fdc4f4723d5e005ef1af611814490b64117a95aea9d5fdab925bced0f9c94d338ec841d6658dbbd88e6e67b5d
|
7
|
+
data.tar.gz: 534dbb03ae216b40205e25e9fc4495f23dda3ab6d90fb3e36201ac25b9c9e57a20d976741e5dd226ff9061bc483426050bfe05bd6148350520a31d09913ce59a
|
data/bookbinder.gemspec
CHANGED
@@ -2,7 +2,7 @@ require 'base64'
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = 'bookbindery'
|
5
|
-
s.version = '9.
|
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
|
-
|
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
|
-
|
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 = {
|
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
|
-
|
58
|
-
|
59
|
-
|
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
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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(
|
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 '
|
3
|
+
require_relative 'hit'
|
4
4
|
|
5
5
|
module Bookbinder
|
6
6
|
module Search
|
7
7
|
class Query
|
8
|
-
|
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
|
13
|
-
|
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
|
-
|
17
|
+
def query_options
|
18
|
+
options = YAML.load_file(File.expand_path('../../../search.yml', __FILE__))
|
16
19
|
|
17
|
-
|
20
|
+
options['from'] = (page_number - 1) * 10
|
21
|
+
options['query']['bool']['should']['query_string']['query'] = search_term
|
18
22
|
|
19
|
-
|
23
|
+
unless product_name.nil?
|
24
|
+
filters = [{
|
25
|
+
'term' => { 'product_name' => product_name }
|
26
|
+
}]
|
20
27
|
|
21
|
-
|
22
|
-
|
28
|
+
unless product_version.nil?
|
29
|
+
filters << {'term' => { 'product_version' => product_version }}
|
30
|
+
end
|
23
31
|
|
24
|
-
|
32
|
+
options['query']['bool']['filter'] = {
|
33
|
+
'bool' => {
|
34
|
+
'must' => filters
|
35
|
+
}
|
36
|
+
}
|
37
|
+
end
|
25
38
|
|
26
|
-
|
27
|
-
|
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
|
-
|
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
|
-
|
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
|
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,
|
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
|
-
<%
|
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="
|
28
|
-
<a class="page previous" href="
|
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="
|
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="
|
44
|
-
<a class="page last" href="
|
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 %>
|
data/template_app/search.yml
CHANGED
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
|
+
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-
|
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
|