bookbindery 9.5.0 → 9.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/bookbinder.gemspec +3 -1
  3. data/lib/bookbinder/commands/collection.rb +1 -1
  4. data/lib/bookbinder/commands/generate.rb +1 -1
  5. data/lib/bookbinder/css_link_checker.rb +6 -2
  6. data/lib/bookbinder/preprocessing/dita_html_preprocessor.rb +3 -3
  7. data/lib/bookbinder/preprocessing/link_to_site_gen_dir.rb +2 -2
  8. data/lib/bookbinder/subnav/{json_from_html_toc.rb → navigation_entries_from_html_toc.rb} +3 -5
  9. data/lib/bookbinder/subnav/{json_from_markdown_toc.rb → navigation_entries_from_markdown_root.rb} +4 -4
  10. data/lib/bookbinder/subnav/pdf_config_creator.rb +3 -5
  11. data/lib/bookbinder/subnav/subnav_generator.rb +9 -6
  12. data/lib/bookbinder/subnav/subnav_generator_factory.rb +2 -8
  13. data/lib/bookbinder/subnav/template_creator.rb +33 -21
  14. data/master_middleman/archive_drop_down_menu.rb +3 -3
  15. data/master_middleman/bookbinder_helpers.rb +1 -1
  16. data/master_middleman/source/javascripts/sidenav.js +45 -0
  17. data/master_middleman/source/layouts/_additional-scripts.erb +0 -0
  18. data/master_middleman/source/layouts/_book-footer.erb +0 -0
  19. data/master_middleman/source/layouts/_book-search.erb +0 -0
  20. data/master_middleman/source/layouts/_book-title.erb +3 -0
  21. data/master_middleman/source/layouts/_header.erb +34 -0
  22. data/master_middleman/source/layouts/_local-header.erb +0 -0
  23. data/master_middleman/source/layouts/layout.erb +73 -0
  24. data/master_middleman/source/stylesheets/base.scss +365 -0
  25. data/master_middleman/source/stylesheets/partials/_book-base-values.scss +0 -0
  26. data/master_middleman/source/stylesheets/partials/_book-vars.scss +0 -0
  27. data/master_middleman/source/stylesheets/partials/_default.scss +300 -0
  28. data/master_middleman/source/stylesheets/partials/_footer.scss +63 -0
  29. data/master_middleman/source/stylesheets/partials/_header.scss +429 -0
  30. data/master_middleman/source/stylesheets/partials/_mixins.scss +43 -0
  31. data/master_middleman/source/stylesheets/partials/_reset.scss +233 -0
  32. data/master_middleman/source/stylesheets/partials/_search.scss +78 -0
  33. data/master_middleman/source/stylesheets/partials/_sidenav.scss +143 -0
  34. data/master_middleman/source/stylesheets/partials/_syntax-highlight.scss +64 -0
  35. data/master_middleman/source/stylesheets/partials/_vars.scss +62 -0
  36. data/master_middleman/source/subnavs/_default.erb +0 -0
  37. data/master_middleman/source/subnavs/_nav-links.erb +10 -0
  38. data/master_middleman/source/subnavs/_subnav_template.erb +8 -0
  39. metadata +55 -5
  40. data/lib/bookbinder/subnav/json_props_creator.rb +0 -35
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a7fb273894d32de11b696ffd383b8d55ded9b612
4
- data.tar.gz: 916e689fdca4e2386643bfe17b85fce557fb46df
3
+ metadata.gz: 6fce8a509ec467f42d265301238c63732c561114
4
+ data.tar.gz: 102ee2ea961254302f89115dd2c48e1e1a5fdb2b
5
5
  SHA512:
6
- metadata.gz: 4b2e0f90300f0ac55df5d5c48945a03b7249a07fdc4f4723d5e005ef1af611814490b64117a95aea9d5fdab925bced0f9c94d338ec841d6658dbbd88e6e67b5d
7
- data.tar.gz: 534dbb03ae216b40205e25e9fc4495f23dda3ab6d90fb3e36201ac25b9c9e57a20d976741e5dd226ff9061bc483426050bfe05bd6148350520a31d09913ce59a
6
+ metadata.gz: e7f58749e6e832db572c4c65a2fe92decf59de7272c5c1d9c33904ce36ae3d248936a6b7c17796f1f9eef83141b84b1a356ec8c1f925653c00e579320e79cfe7
7
+ data.tar.gz: 100960ac745d0eb90ef8f7cb0cad49df23492a62fd9278aeb12773bb377cc7e3687bf89be10ba0f53a500ce3082599797a16ea9c08285d054a99e70f5d02c2d3
@@ -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.0'
5
+ s.version = '9.6.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']
@@ -31,10 +31,12 @@ Gem::Specification.new do |s|
31
31
  s.add_runtime_dependency 'nokogiri', ['1.6.7.2']
32
32
  s.add_runtime_dependency 'thor'
33
33
  s.add_runtime_dependency 'elasticsearch'
34
+ s.add_runtime_dependency 'font-awesome-sass'
34
35
 
35
36
  s.add_development_dependency 'license_finder'
36
37
  s.add_development_dependency 'pry-byebug'
37
38
  s.add_development_dependency 'rake'
38
39
  s.add_development_dependency 'rspec'
39
40
  s.add_development_dependency 'sendgrid-ruby'
41
+ s.add_development_dependency 'jasmine'
40
42
  end
@@ -1,5 +1,5 @@
1
1
  Dir.glob(File.expand_path('../../commands/*.rb', __FILE__)).each do |command_file|
2
- require command_file
2
+ require command_file unless command_file =~ /collection\.rb\z/
3
3
  end
4
4
 
5
5
  require_relative '../commands/components/bind/directory_preparer'
@@ -12,7 +12,7 @@ module Bookbinder
12
12
 
13
13
  def run(name, special_bookbinder_gem_args={})
14
14
  path = context_dir.join(name)
15
- streams[:out].puts "Generating book at #{path}"
15
+ streams[:out].puts "Generating book at #{path}..."
16
16
  if fs.file_exist?(path)
17
17
  streams[:err].puts "Cannot generate book: directory already exists"
18
18
  1
@@ -42,14 +42,18 @@ module Bookbinder
42
42
  case link
43
43
  when data_uri then true
44
44
  when remote_uri then http_reachable?(link)
45
- when absolute_uri then File.exists?(File.join('.', 'public', link))
45
+ when absolute_uri then File.exists?(File.join('.', 'public', path_info(link)))
46
46
  when relative_uri then
47
47
  dirs = dirs.split('/')[0...-1]
48
- computed_uri = File.expand_path(File.join dirs, link)
48
+ computed_uri = File.expand_path(File.join dirs, path_info(link))
49
49
  File.exists?(computed_uri)
50
50
  end
51
51
  end
52
52
 
53
+ def path_info(link)
54
+ link.sub(/[?#].+\z/, '')
55
+ end
56
+
53
57
  def strip_location(id)
54
58
  dirs, filepath = id.split('=> ')
55
59
  [dirs, filepath]
@@ -1,5 +1,5 @@
1
1
  require_relative '../values/subnav_template'
2
- require_relative '../../../lib/bookbinder/subnav/json_from_html_toc'
2
+ require_relative '../../../lib/bookbinder/subnav/navigation_entries_from_html_toc'
3
3
 
4
4
  module Bookbinder
5
5
  module Preprocessing
@@ -43,7 +43,7 @@ module Bookbinder
43
43
 
44
44
  private
45
45
 
46
- attr_reader :fs, :subnav_gen_factory, :dita_formatter, :command_creator, :sheller, :subnav_generator, :output_locations
46
+ attr_reader :fs, :subnav_gen_factory, :dita_formatter, :command_creator, :sheller, :output_locations
47
47
 
48
48
  def section_html_dir(section)
49
49
  output_locations.html_from_preprocessing_dir.join(section.destination_directory)
@@ -84,7 +84,7 @@ module Bookbinder
84
84
 
85
85
 
86
86
  def subnav_generator
87
- @subnav_generator ||= subnav_gen_factory.produce(Subnav::JsonFromHtmlToc.new(fs))
87
+ @subnav_generator ||= subnav_gen_factory.produce(Subnav::NavigationEntriesFromHtmlToc.new(fs))
88
88
  end
89
89
  end
90
90
  end
@@ -1,5 +1,5 @@
1
1
  require_relative '../subnav/subnav_generator'
2
- require_relative '../subnav/json_from_markdown_toc'
2
+ require_relative '../subnav/navigation_entries_from_markdown_root'
3
3
 
4
4
  module Bookbinder
5
5
  module Preprocessing
@@ -30,7 +30,7 @@ module Bookbinder
30
30
  private
31
31
 
32
32
  def subnav_generator(require_valid_subnav_links)
33
- @subnav_generator ||= subnav_generator_factory.produce(Subnav::JsonFromMarkdownToc.new(filesystem, require_valid_subnav_links))
33
+ @subnav_generator ||= subnav_generator_factory.produce(Subnav::NavigationEntriesFromMarkdownRoot.new(filesystem, require_valid_subnav_links))
34
34
  end
35
35
 
36
36
  attr_reader :filesystem, :subnav_generator_factory
@@ -3,7 +3,7 @@ require 'active_support/all'
3
3
 
4
4
  module Bookbinder
5
5
  module Subnav
6
- class JsonFromHtmlToc
6
+ class NavigationEntriesFromHtmlToc
7
7
  def initialize(fs)
8
8
  @fs = fs
9
9
  end
@@ -14,9 +14,7 @@ module Bookbinder
14
14
  doc = parse_toc_file
15
15
  set_anchor_values(doc.css('a'))
16
16
 
17
- {
18
- links: gather_urls_and_texts(doc.css('body > ul'))
19
- }.to_json
17
+ gather_urls_and_texts(doc.css('body > ul'))
20
18
  end
21
19
 
22
20
  private
@@ -47,7 +45,7 @@ module Bookbinder
47
45
  text = anchor.inner_text
48
46
  ul = li.css('> ul')
49
47
  if ul.size > 0
50
- {url: href, text: text, nestedLinks: gather_urls_and_texts(ul)}
48
+ {url: href, text: text, nested_links: gather_urls_and_texts(ul)}
51
49
  else
52
50
  {url: href, text: text}
53
51
  end
@@ -4,7 +4,7 @@ require 'redcarpet'
4
4
 
5
5
  module Bookbinder
6
6
  module Subnav
7
- class JsonFromMarkdownToc
7
+ class NavigationEntriesFromMarkdownRoot
8
8
  SubnavDuplicateLinkError = Class.new(RuntimeError)
9
9
  SubnavBrokenLinkError = Class.new(RuntimeError)
10
10
  SubnavRootMissingError = Class.new(RuntimeError)
@@ -25,13 +25,13 @@ module Bookbinder
25
25
  if @require_valid_subnav_links
26
26
  raise SubnavRootMissingError.new('Subnav root not found at: ' + config.subnav_root)
27
27
  else
28
- return {links: []}.to_json
28
+ return []
29
29
  end
30
30
  end
31
31
 
32
32
  @parsed_files = {Pathname(root) => '(root)'}
33
33
 
34
- {links: gather_urls_and_texts(root)}.to_json
34
+ gather_urls_and_texts(root)
35
35
  end
36
36
 
37
37
  attr_reader :fs, :source_for_site_gen, :renderer, :config
@@ -67,7 +67,7 @@ module Bookbinder
67
67
  unless no_children
68
68
  @parsed_files[next_source] = source
69
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?
70
+ nested_links.merge!(nested_links: nested_urls_and_texts) unless nested_urls_and_texts.empty?
71
71
  end
72
72
 
73
73
  {url: '/' + expanded_href.to_s, text: element.inner_text}.merge(nested_links)
@@ -1,5 +1,4 @@
1
1
  require 'yaml'
2
- require "json"
3
2
 
4
3
  module Bookbinder
5
4
  module Subnav
@@ -9,9 +8,8 @@ module Bookbinder
9
8
  @output_locations = output_locations
10
9
  end
11
10
 
12
- def create(props_filename, subnav_config)
13
- json = JSON.parse(fs.read(props_location(props_filename)))
14
- @links = format_links(json['links'])
11
+ def create(navigation_entries, subnav_config)
12
+ @links = format_links(navigation_entries)
15
13
 
16
14
  fs.overwrite(to: output_locations.pdf_config_dir.join(subnav_config.pdf_config),
17
15
  text: config_content)
@@ -26,7 +24,7 @@ module Bookbinder
26
24
  end
27
25
 
28
26
  def format_links(links)
29
- links.map{|item| item['url'] }.compact.map{|link| link.sub(/^\//, '')}
27
+ links.map{|item| item[:url] }.compact.map{|link| link.sub(/^\//, '')}
30
28
  end
31
29
 
32
30
  def config_content
@@ -1,22 +1,25 @@
1
1
  module Bookbinder
2
2
  module Subnav
3
3
  class SubnavGenerator
4
- def initialize(json_props_creator, template_creator, pdf_config_creator)
5
- @json_props_creator = json_props_creator
4
+ def initialize(navigation_entries_parser, template_creator, pdf_config_creator, output_locations)
5
+ @navigation_entries_parser = navigation_entries_parser
6
6
  @template_creator = template_creator
7
7
  @pdf_config_creator = pdf_config_creator
8
+ @output_locations = output_locations
8
9
  end
9
10
 
10
11
  def generate(subnav_spec)
11
- filename = json_props_creator.create(subnav_spec)
12
- template_creator.create(filename, subnav_spec)
13
- pdf_config_creator.create(filename, subnav_spec) if pdf?(subnav_spec)
12
+ navigation_entries = navigation_entries_parser.get_links(subnav_spec, output_locations)
13
+ template_creator.create(navigation_entries, subnav_spec)
14
+ pdf_config_creator.create(navigation_entries, subnav_spec) if pdf?(subnav_spec)
14
15
  end
15
16
 
16
- attr_reader :json_props_creator, :template_creator, :pdf_config_creator
17
+ attr_reader :navigation_entries_parser, :template_creator, :pdf_config_creator
17
18
 
18
19
  private
19
20
 
21
+ attr_reader :output_locations
22
+
20
23
  def pdf?(subnav_spec)
21
24
  subnav_spec.respond_to?(:pdf_config) && subnav_spec.pdf_config
22
25
  end
@@ -1,7 +1,5 @@
1
- require_relative 'json_props_creator'
2
1
  require_relative 'template_creator'
3
2
  require_relative 'pdf_config_creator'
4
- require_relative '../html_document_manipulator'
5
3
 
6
4
  module Bookbinder
7
5
  module Subnav
@@ -12,19 +10,15 @@ module Bookbinder
12
10
  end
13
11
 
14
12
  def produce(json_generator)
15
- SubnavGenerator.new(json_props_creator(json_generator), template_creator, pdf_config_creator)
13
+ SubnavGenerator.new(json_generator, template_creator, pdf_config_creator, output_locations)
16
14
  end
17
15
 
18
16
  attr_reader :fs, :output_locations
19
17
 
20
18
  private
21
19
 
22
- def json_props_creator(json_generator)
23
- @json_props_creator ||= JsonPropsCreator.new(fs, output_locations, json_generator)
24
- end
25
-
26
20
  def template_creator
27
- @template_creator ||= TemplateCreator.new(fs, output_locations, HtmlDocumentManipulator.new)
21
+ @template_creator ||= TemplateCreator.new(fs, output_locations)
28
22
  end
29
23
 
30
24
  def pdf_config_creator
@@ -1,24 +1,20 @@
1
- require_relative '../../../lib/bookbinder/values/user_message'
2
- require_relative '../../../lib/bookbinder/colorizer'
3
- require_relative '../../../lib/bookbinder/terminal'
1
+ require 'erb'
4
2
 
5
3
  module Bookbinder
6
4
  module Subnav
7
5
  class TemplateCreator
8
- def initialize(fs, output_locations, html_doc_manipulator)
6
+ def initialize(fs, output_locations)
9
7
  @fs = fs
10
8
  @output_locations = output_locations
11
- @html_doc_manipulator = html_doc_manipulator
12
9
  end
13
10
 
14
- def create(props_filename, subnav_spec)
11
+ def create(navigation_entries, subnav_spec)
15
12
  template_content = fs.read(template_path)
16
- nav_with_props = html_doc_manipulator.set_attribute(document: template_content,
17
- selector: 'div.nav-content',
18
- attribute: 'data-props-location',
19
- value: props_filename)
13
+ links_template = ERB.new(fs.read(subnavs_path.join('_nav-links.erb')))
20
14
 
21
- fs.write(text: nav_with_props, to: subnav_destination(subnav_spec.subnav_name))
15
+ populated_nav = ERB.new(template_content).result(LinkHolder.new(navigation_entries, links_template).get_binding)
16
+
17
+ fs.write(text: populated_nav, to: subnav_destination(subnav_spec.subnav_name))
22
18
  end
23
19
 
24
20
  attr_reader :fs, :output_locations, :html_doc_manipulator
@@ -34,21 +30,37 @@ module Bookbinder
34
30
  end
35
31
 
36
32
  def template_path
37
- deprecated_prefix = '_dita_' unless fs.file_exist?(subnavs_path.join('subnav_template.erb'))
38
-
39
- if deprecated_prefix
40
- Terminal.new(Colorizer.new).update(UserMessage.new(
41
- "Use of '_dita_subnav_template.erb' is deprecated. " +
42
- "The preferred template is 'subnav_template.erb'. Please rename your file.",
43
- EscalationType.warn
44
- ))
45
- end
46
- subnavs_path.join("#{deprecated_prefix}subnav_template.erb")
33
+ subnavs_path.join('_subnav_template.erb')
47
34
  end
48
35
 
49
36
  def subnav_destination(name)
50
37
  subnavs_path.join(filename(name))
51
38
  end
39
+
40
+ class LinkHolder
41
+ def initialize(links, template)
42
+ @links = links
43
+ @template = template
44
+ end
45
+
46
+ attr_reader :links
47
+
48
+ def get_binding
49
+ binding
50
+ end
51
+
52
+ def render_links(some_links)
53
+ @template.result(LinkHolder.new(some_links, @template).get_binding)
54
+ end
55
+
56
+ def submenu_class(link)
57
+ 'has_submenu' unless links?(link[:nested_links])
58
+ end
59
+
60
+ def links?(links)
61
+ (links || []).empty?
62
+ end
63
+ end
52
64
  end
53
65
  end
54
66
  end
@@ -1,7 +1,7 @@
1
1
  module Bookbinder
2
2
  class ArchiveDropDownMenu
3
3
  def initialize(config, current_path: nil)
4
- @config = config || default_config
4
+ @config = config_with_default(config)
5
5
  @current_path = current_path
6
6
  end
7
7
 
@@ -35,8 +35,8 @@ module Bookbinder
35
35
  File.dirname(current_path)
36
36
  end
37
37
 
38
- def default_config
39
- { root_menu_reference => empty_menu }
38
+ def config_with_default(config)
39
+ { root_menu_reference => empty_menu }.merge(config || {})
40
40
  end
41
41
 
42
42
  def empty_menu
@@ -144,7 +144,7 @@ module Bookbinder
144
144
  path = current_path.dup
145
145
  end
146
146
  basename = File.basename(path)
147
- dirname = File.dirname(path).gsub(/\./, '_')
147
+ dirname = File.dirname(path).gsub('.', '_')
148
148
  page_classes(File.join(dirname, basename), options)
149
149
  end
150
150
 
@@ -0,0 +1,45 @@
1
+ (function() {
2
+ var isExpanded = /\bexpanded\b/;
3
+
4
+ function openSubmenu(e) {
5
+ var el = e.srcElement;
6
+ if (isExpanded.test(el.className)) {
7
+ el.className = el.className.replace(isExpanded, '');
8
+ } else {
9
+ el.className += ' expanded';
10
+ }
11
+ e.stopPropagation();
12
+ }
13
+
14
+ window.Bookbinder = {
15
+ startSidenav: function(rootEl, currentPath) {
16
+ var submenus = rootEl.querySelectorAll('.has_submenu');
17
+
18
+ for (var i = 0; i < submenus.length; i++) {
19
+ submenus[i].onclick = openSubmenu;
20
+ }
21
+
22
+ if (currentPath) {
23
+ var currentLink = rootEl.querySelector('a[href="' + currentPath + '"]');
24
+ if (currentLink) {
25
+ currentLink.className += ' active';
26
+
27
+ var hasSubmenu = /\bhas_submenu\b/;
28
+ var subnavLocation = currentLink.parentNode;
29
+
30
+ while(subnavLocation.parentNode !== rootEl) {
31
+ subnavLocation = subnavLocation.parentNode;
32
+ if (hasSubmenu.test(subnavLocation.className)) {
33
+ subnavLocation.className += ' expanded';
34
+ }
35
+ }
36
+
37
+ rootEl.scrollTop = currentLink.offsetTop - rootEl.offsetTop;
38
+ }
39
+ }
40
+ },
41
+ boot: function() {
42
+ Bookbinder.startSidenav(document.querySelector('#sub-nav'), document.location.pathname);
43
+ }
44
+ };
45
+ })();
@@ -0,0 +1,3 @@
1
+ <!--Default title-->
2
+ <!--If book needs something different, add a book-title partial to the book's layouts folder-->
3
+ <%= vars.title %>
@@ -0,0 +1,34 @@
1
+ <% if current_page.data.title %> <%# this is a proxy for if !homepage %>
2
+ <header class="header header-layout">
3
+ <h1 class="logo">
4
+ <a href="/"><%= vars.book_title || 'Default Book Title' %></a>
5
+ </h1>
6
+ <%= yield_for_archive_drop_down_menu %>
7
+ <div class="header-links js-bar-links">
8
+ <div class="btn-menu" data-behavior="MenuMobile"></div>
9
+ <%= vars.product_link %>
10
+ <div class="header-item">
11
+ <%= vars.support_link %>
12
+ </div>
13
+ <%= partial 'layouts/book-search' %>
14
+ </div>
15
+ </header>
16
+ <% else %>
17
+ <header class="header-home">
18
+ <div class="home-links js-bar-links">
19
+ <div class="btn-menu" data-behavior="MenuMobile"></div>
20
+ <%= vars.product_link %>
21
+ <div class="header-item">
22
+ <%= vars.support_call_to_action %>
23
+ </div>
24
+ <%= partial 'layouts/book-search' %>
25
+ </div>
26
+ <h1 class="title-flashy">
27
+ <%= partial 'layouts/book-title' %>
28
+ </h1>
29
+
30
+ <h2 class="title-intro">
31
+ <%= vars.hero_text %>
32
+ </h2>
33
+ </header>
34
+ <% end %>