alb3rtobr-test 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bookbinder.gemspec +43 -0
- data/install_bin/bookbinder +5 -0
- data/lib/bookbinder/cli.rb +105 -0
- data/lib/bookbinder/code_example_reader.rb +95 -0
- data/lib/bookbinder/colorizer.rb +16 -0
- data/lib/bookbinder/commands/bind.rb +120 -0
- data/lib/bookbinder/commands/collection.rb +181 -0
- data/lib/bookbinder/commands/components/bind/directory_preparer.rb +33 -0
- data/lib/bookbinder/commands/components/bind/layout_preparer.rb +27 -0
- data/lib/bookbinder/commands/components/command_options.rb +45 -0
- data/lib/bookbinder/commands/components/imprint/directory_preparer.rb +24 -0
- data/lib/bookbinder/commands/generate.rb +92 -0
- data/lib/bookbinder/commands/imprint.rb +55 -0
- data/lib/bookbinder/commands/punch.rb +33 -0
- data/lib/bookbinder/commands/update_local_doc_repos.rb +42 -0
- data/lib/bookbinder/commands/watch.rb +100 -0
- data/lib/bookbinder/config/checkers/archive_menu_checker.rb +29 -0
- data/lib/bookbinder/config/checkers/ditamap_presence_checker.rb +27 -0
- data/lib/bookbinder/config/checkers/duplicate_section_name_checker.rb +33 -0
- data/lib/bookbinder/config/checkers/products_checker.rb +34 -0
- data/lib/bookbinder/config/checkers/repository_name_presence_checker.rb +34 -0
- data/lib/bookbinder/config/checkers/required_keys_checker.rb +18 -0
- data/lib/bookbinder/config/checkers/section_presence_checker.rb +15 -0
- data/lib/bookbinder/config/configuration.rb +119 -0
- data/lib/bookbinder/config/configuration_decorator.rb +54 -0
- data/lib/bookbinder/config/dita_config_generator.rb +61 -0
- data/lib/bookbinder/config/fetcher.rb +64 -0
- data/lib/bookbinder/config/imprint/configuration.rb +24 -0
- data/lib/bookbinder/config/product_config.rb +34 -0
- data/lib/bookbinder/config/section_config.rb +85 -0
- data/lib/bookbinder/config/validator.rb +33 -0
- data/lib/bookbinder/config/yaml_loader.rb +34 -0
- data/lib/bookbinder/css_link_checker.rb +67 -0
- data/lib/bookbinder/directory_helpers.rb +15 -0
- data/lib/bookbinder/dita_command_creator.rb +95 -0
- data/lib/bookbinder/dita_html_for_middleman_formatter.rb +45 -0
- data/lib/bookbinder/errors/programmer_mistake.rb +5 -0
- data/lib/bookbinder/html_document_manipulator.rb +21 -0
- data/lib/bookbinder/ingest/cloner_factory.rb +26 -0
- data/lib/bookbinder/ingest/destination_directory.rb +21 -0
- data/lib/bookbinder/ingest/git_accessor.rb +102 -0
- data/lib/bookbinder/ingest/git_cloner.rb +36 -0
- data/lib/bookbinder/ingest/local_filesystem_cloner.rb +66 -0
- data/lib/bookbinder/ingest/missing_working_copy.rb +27 -0
- data/lib/bookbinder/ingest/repo_identifier.rb +45 -0
- data/lib/bookbinder/ingest/section_repository.rb +49 -0
- data/lib/bookbinder/ingest/update_failure.rb +15 -0
- data/lib/bookbinder/ingest/update_success.rb +12 -0
- data/lib/bookbinder/ingest/working_copy.rb +36 -0
- data/lib/bookbinder/local_filesystem_accessor.rb +122 -0
- data/lib/bookbinder/middleman_runner.rb +50 -0
- data/lib/bookbinder/postprocessing/link_checker.rb +125 -0
- data/lib/bookbinder/postprocessing/redirection.rb +38 -0
- data/lib/bookbinder/preprocessing/dita_html_preprocessor.rb +91 -0
- data/lib/bookbinder/preprocessing/dita_pdf_preprocessor.rb +48 -0
- data/lib/bookbinder/preprocessing/link_to_site_gen_dir.rb +39 -0
- data/lib/bookbinder/preprocessing/preprocessor.rb +26 -0
- data/lib/bookbinder/server_director.rb +30 -0
- data/lib/bookbinder/sheller.rb +52 -0
- data/lib/bookbinder/streams/colorized_stream.rb +25 -0
- data/lib/bookbinder/streams/filter_stream.rb +22 -0
- data/lib/bookbinder/subnav/navigation_entries_from_html_toc.rb +59 -0
- data/lib/bookbinder/subnav/navigation_entries_from_markdown_root.rb +116 -0
- data/lib/bookbinder/subnav/pdf_config_creator.rb +50 -0
- data/lib/bookbinder/subnav/subnav_generator.rb +28 -0
- data/lib/bookbinder/subnav/subnav_generator_factory.rb +29 -0
- data/lib/bookbinder/subnav/template_creator.rb +71 -0
- data/lib/bookbinder/terminal.rb +19 -0
- data/lib/bookbinder/values/output_locations.rb +91 -0
- data/lib/bookbinder/values/product_info.rb +11 -0
- data/lib/bookbinder/values/section.rb +58 -0
- data/lib/bookbinder/values/subnav_template.rb +4 -0
- data/lib/bookbinder/values/user_message.rb +15 -0
- data/master_middleman/archive_drop_down_menu.rb +50 -0
- data/master_middleman/bookbinder_helpers.rb +282 -0
- data/master_middleman/compass_runner.rb +0 -0
- data/master_middleman/config.rb +45 -0
- data/master_middleman/proof.rb +90 -0
- data/master_middleman/quicklinks_renderer.rb +80 -0
- data/master_middleman/source/javascripts/all.js +2 -0
- data/master_middleman/source/javascripts/book.js +1 -0
- data/master_middleman/source/javascripts/bookbinder.js +130 -0
- data/master_middleman/source/layouts/_additional-scripts.erb +0 -0
- data/master_middleman/source/layouts/_book-footer.erb +0 -0
- data/master_middleman/source/layouts/_book-search.erb +0 -0
- data/master_middleman/source/layouts/_book-title.erb +3 -0
- data/master_middleman/source/layouts/_header.erb +34 -0
- data/master_middleman/source/layouts/_local-header.erb +0 -0
- data/master_middleman/source/layouts/_page-footer.erb +1 -0
- data/master_middleman/source/layouts/_title.erb +5 -0
- data/master_middleman/source/layouts/layout.erb +70 -0
- data/master_middleman/source/stylesheets/all.css.scss +3 -0
- data/master_middleman/source/stylesheets/base.scss +324 -0
- data/master_middleman/source/stylesheets/book-styles.scss +0 -0
- data/master_middleman/source/stylesheets/layout-styles.scss +0 -0
- data/master_middleman/source/stylesheets/partials/_book-base-values.scss +0 -0
- data/master_middleman/source/stylesheets/partials/_book-vars.scss +0 -0
- data/master_middleman/source/stylesheets/partials/_default.scss +302 -0
- data/master_middleman/source/stylesheets/partials/_footer.scss +64 -0
- data/master_middleman/source/stylesheets/partials/_header.scss +419 -0
- data/master_middleman/source/stylesheets/partials/_layout-vars.scss +0 -0
- data/master_middleman/source/stylesheets/partials/_mixins.scss +53 -0
- data/master_middleman/source/stylesheets/partials/_reset.scss +233 -0
- data/master_middleman/source/stylesheets/partials/_search.scss +78 -0
- data/master_middleman/source/stylesheets/partials/_sidenav.scss +191 -0
- data/master_middleman/source/stylesheets/partials/_syntax-highlight.scss +64 -0
- data/master_middleman/source/stylesheets/partials/_vars.scss +64 -0
- data/master_middleman/source/stylesheets/print-book-styles.scss +0 -0
- data/master_middleman/source/stylesheets/print-layout-styles.scss +0 -0
- data/master_middleman/source/stylesheets/print.css.scss +57 -0
- data/master_middleman/source/subnavs/_default.erb +0 -0
- data/master_middleman/source/subnavs/_nav-links.erb +10 -0
- data/master_middleman/source/subnavs/_subnav_template.erb +8 -0
- data/master_middleman/subdirectory_aware_assets.rb +36 -0
- data/template_app/Gemfile +10 -0
- data/template_app/Gemfile.lock +46 -0
- data/template_app/config.ru +9 -0
- data/template_app/lib/rack_static_if_exists.rb +19 -0
- data/template_app/lib/search/handler.rb +73 -0
- data/template_app/lib/search/hit.rb +21 -0
- data/template_app/lib/search/query.rb +74 -0
- data/template_app/lib/search/renderer.rb +30 -0
- data/template_app/lib/server.rb +52 -0
- data/template_app/mail_sender.rb +61 -0
- data/template_app/rack_app.rb +110 -0
- data/template_app/search-results.html.erb +81 -0
- data/template_app/search.yml +23 -0
- metadata +562 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative 'template_creator'
|
2
|
+
require_relative 'pdf_config_creator'
|
3
|
+
|
4
|
+
module Bookbinder
|
5
|
+
module Subnav
|
6
|
+
class SubnavGeneratorFactory
|
7
|
+
def initialize(fs, output_locations)
|
8
|
+
@fs = fs
|
9
|
+
@output_locations = output_locations
|
10
|
+
end
|
11
|
+
|
12
|
+
def produce(json_generator)
|
13
|
+
SubnavGenerator.new(json_generator, template_creator, pdf_config_creator, output_locations)
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :fs, :output_locations
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def template_creator
|
21
|
+
@template_creator ||= TemplateCreator.new(fs, output_locations)
|
22
|
+
end
|
23
|
+
|
24
|
+
def pdf_config_creator
|
25
|
+
@pdf_config_creator ||= PdfConfigCreator.new(fs, output_locations)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'rack/utils'
|
3
|
+
|
4
|
+
module Bookbinder
|
5
|
+
module Subnav
|
6
|
+
class TemplateCreator
|
7
|
+
def initialize(fs, output_locations)
|
8
|
+
@fs = fs
|
9
|
+
@output_locations = output_locations
|
10
|
+
end
|
11
|
+
|
12
|
+
def create(navigation_entries, subnav_spec)
|
13
|
+
template_content = fs.read(template_path)
|
14
|
+
links_template = ERB.new(fs.read(subnavs_path.join('_nav-links.erb')))
|
15
|
+
|
16
|
+
populated_nav = ERB.new(template_content).result(LinkHolder.new(navigation_entries, links_template).get_binding)
|
17
|
+
|
18
|
+
fs.write(text: populated_nav, to: subnav_destination(subnav_spec.subnav_name))
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_reader :fs, :output_locations, :html_doc_manipulator
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def subnavs_path
|
26
|
+
output_locations.subnavs_for_layout_dir
|
27
|
+
end
|
28
|
+
|
29
|
+
def filename(name)
|
30
|
+
"#{name}.erb"
|
31
|
+
end
|
32
|
+
|
33
|
+
def template_path
|
34
|
+
subnavs_path.join('_subnav_template.erb')
|
35
|
+
end
|
36
|
+
|
37
|
+
def subnav_destination(name)
|
38
|
+
subnavs_path.join(filename(name))
|
39
|
+
end
|
40
|
+
|
41
|
+
class LinkHolder
|
42
|
+
def initialize(links, template)
|
43
|
+
@links = links
|
44
|
+
@template = template
|
45
|
+
end
|
46
|
+
|
47
|
+
attr_reader :links
|
48
|
+
|
49
|
+
def get_binding
|
50
|
+
binding
|
51
|
+
end
|
52
|
+
|
53
|
+
def render_links(some_links)
|
54
|
+
@template.result(LinkHolder.new(some_links, @template).get_binding)
|
55
|
+
end
|
56
|
+
|
57
|
+
def submenu_class(link)
|
58
|
+
'has_submenu' unless links?(link[:nested_links])
|
59
|
+
end
|
60
|
+
|
61
|
+
def links?(links)
|
62
|
+
(links || []).empty?
|
63
|
+
end
|
64
|
+
|
65
|
+
def escape_html(str)
|
66
|
+
Rack::Utils.escape_html(str)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative 'colorizer'
|
2
|
+
|
3
|
+
module Bookbinder
|
4
|
+
class Terminal
|
5
|
+
def initialize(colorizer)
|
6
|
+
@colorizer = colorizer
|
7
|
+
end
|
8
|
+
|
9
|
+
def update(user_message)
|
10
|
+
if user_message.error?
|
11
|
+
error_message = @colorizer.colorize(user_message.message, Colorizer::Colors.red)
|
12
|
+
$stderr.puts error_message
|
13
|
+
elsif user_message.warn?
|
14
|
+
warning_message = @colorizer.colorize(user_message.message, Colorizer::Colors.yellow)
|
15
|
+
puts warning_message
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require_relative '../directory_helpers'
|
2
|
+
require_relative '../errors/programmer_mistake'
|
3
|
+
|
4
|
+
module Bookbinder
|
5
|
+
class OutputLocations
|
6
|
+
include DirectoryHelperMethods
|
7
|
+
|
8
|
+
def initialize(final_app_dir: nil, context_dir: nil)
|
9
|
+
@final_app_dir = final_app_dir
|
10
|
+
@context_dir = context_dir
|
11
|
+
end
|
12
|
+
|
13
|
+
def final_app_dir
|
14
|
+
Pathname(@final_app_dir)
|
15
|
+
end
|
16
|
+
|
17
|
+
def public_dir
|
18
|
+
final_app_dir.join('public')
|
19
|
+
end
|
20
|
+
|
21
|
+
def build_dir
|
22
|
+
master_dir.join('build/.')
|
23
|
+
end
|
24
|
+
|
25
|
+
def workspace_dir
|
26
|
+
master_dir.join('source')
|
27
|
+
end
|
28
|
+
|
29
|
+
def master_dir
|
30
|
+
output_dir.join('master_middleman')
|
31
|
+
end
|
32
|
+
|
33
|
+
def output_dir
|
34
|
+
context_dir.join(output_dir_name)
|
35
|
+
end
|
36
|
+
|
37
|
+
def preprocessing_home_dir
|
38
|
+
output_dir.join('preprocessing')
|
39
|
+
end
|
40
|
+
|
41
|
+
def cloned_preprocessing_dir
|
42
|
+
preprocessing_home_dir.join('sections')
|
43
|
+
end
|
44
|
+
|
45
|
+
def html_from_preprocessing_dir
|
46
|
+
preprocessing_home_dir.join('html_from_preprocessing')
|
47
|
+
end
|
48
|
+
|
49
|
+
def pdf_from_preprocessing_dir
|
50
|
+
preprocessing_home_dir.join('pdf_from_preprocessing')
|
51
|
+
end
|
52
|
+
|
53
|
+
def formatted_dir
|
54
|
+
preprocessing_home_dir.join('site_generator_ready')
|
55
|
+
end
|
56
|
+
|
57
|
+
def site_generator_home
|
58
|
+
output_dir.join('master_middleman')
|
59
|
+
end
|
60
|
+
|
61
|
+
def source_for_site_generator
|
62
|
+
site_generator_home.join('source')
|
63
|
+
end
|
64
|
+
|
65
|
+
def subnavs_for_layout_dir
|
66
|
+
source_for_site_generator.join('subnavs')
|
67
|
+
end
|
68
|
+
|
69
|
+
def pdf_config_dir
|
70
|
+
context_dir
|
71
|
+
end
|
72
|
+
|
73
|
+
def artifact_dir
|
74
|
+
context_dir.join('artifacts')
|
75
|
+
end
|
76
|
+
|
77
|
+
def pdf_artifact_dir
|
78
|
+
artifact_dir.join('pdfs')
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def context_dir
|
84
|
+
if @context_dir.nil?
|
85
|
+
raise Errors::ProgrammerMistake.new("You must provide a context_dir to OutputLocations")
|
86
|
+
else
|
87
|
+
Pathname(@context_dir)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require_relative '../errors/programmer_mistake'
|
2
|
+
require_relative '../ingest/destination_directory'
|
3
|
+
|
4
|
+
module Bookbinder
|
5
|
+
Section = Struct.new(
|
6
|
+
:path_to_repository,
|
7
|
+
:full_name,
|
8
|
+
:desired_directory_name,
|
9
|
+
:subnav_templ,
|
10
|
+
:desired_subnav_name,
|
11
|
+
:preprocessor_config,
|
12
|
+
:at_repo_path,
|
13
|
+
:repo_name,
|
14
|
+
:source_ref,
|
15
|
+
:pdf_output_filename,
|
16
|
+
:product_info) do
|
17
|
+
|
18
|
+
def path_to_repo_dir
|
19
|
+
at_repo_path.nil? ? path_to_repository : path_to_repository.join(at_repo_path)
|
20
|
+
end
|
21
|
+
|
22
|
+
def subnav_template
|
23
|
+
subnav_templ.sub(/^_/, '').sub(/\.erb$/, '') if subnav_templ
|
24
|
+
end
|
25
|
+
|
26
|
+
def destination_directory
|
27
|
+
Ingest::DestinationDirectory.new(full_name, desired_directory_name)
|
28
|
+
end
|
29
|
+
|
30
|
+
def subnav
|
31
|
+
{namespace => subnav_name}
|
32
|
+
end
|
33
|
+
|
34
|
+
def namespace
|
35
|
+
destination_directory.to_s.gsub(%r{[./]}, '_')
|
36
|
+
end
|
37
|
+
|
38
|
+
def subnav_name
|
39
|
+
subnav_template || desired_subnav_name || 'default'
|
40
|
+
end
|
41
|
+
|
42
|
+
def path_to_preprocessor_attribute(attr)
|
43
|
+
path_to_repo_dir.join(preprocessor_config[attr]) if preprocessor_config[attr]
|
44
|
+
rescue NoMethodError => e
|
45
|
+
raise Errors::ProgrammerMistake.new(
|
46
|
+
"path_to_preprocessor_attribute assumes preprocessor_config is available, got nil.\n" +
|
47
|
+
"Original exception:\n\n#{e.inspect}\n\n#{e.backtrace.join("\n")}"
|
48
|
+
)
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def path_to_repository
|
54
|
+
Pathname(self[:path_to_repository].to_s)
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
module Bookbinder
|
4
|
+
UserMessage = Struct.new(:message, :escalation_type) do
|
5
|
+
def error?
|
6
|
+
escalation_type == EscalationType.error
|
7
|
+
end
|
8
|
+
|
9
|
+
def warn?
|
10
|
+
escalation_type == EscalationType.warn
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
EscalationType = OpenStruct.new(success: 0, error: 1, warn: 2)
|
15
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Bookbinder
|
2
|
+
class ArchiveDropDownMenu
|
3
|
+
def initialize(config, current_path: nil)
|
4
|
+
@config = config_with_default(config)
|
5
|
+
@current_path = current_path
|
6
|
+
end
|
7
|
+
|
8
|
+
def title
|
9
|
+
directory_config.first
|
10
|
+
end
|
11
|
+
|
12
|
+
def dropdown_links
|
13
|
+
versions_to_paths.map { |version_path|
|
14
|
+
{version_path.keys.first => "/#{version_path.values.first}"}
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
def empty?
|
19
|
+
title.nil? && dropdown_links.empty?
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
attr_reader :config, :current_path
|
25
|
+
|
26
|
+
def versions_to_paths
|
27
|
+
directory_config[1..-1]
|
28
|
+
end
|
29
|
+
|
30
|
+
def directory_config
|
31
|
+
config.fetch(directory, config.fetch(root_menu_reference)) || empty_menu
|
32
|
+
end
|
33
|
+
|
34
|
+
def directory
|
35
|
+
File.dirname(current_path)
|
36
|
+
end
|
37
|
+
|
38
|
+
def config_with_default(config)
|
39
|
+
{ root_menu_reference => empty_menu }.merge(config || {})
|
40
|
+
end
|
41
|
+
|
42
|
+
def empty_menu
|
43
|
+
[nil]
|
44
|
+
end
|
45
|
+
|
46
|
+
def root_menu_reference
|
47
|
+
'.'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,282 @@
|
|
1
|
+
require 'bookbinder/code_example_reader'
|
2
|
+
require 'bookbinder/ingest/cloner_factory'
|
3
|
+
require 'bookbinder/ingest/git_accessor'
|
4
|
+
require 'bookbinder/local_filesystem_accessor'
|
5
|
+
require 'date'
|
6
|
+
require_relative 'archive_drop_down_menu'
|
7
|
+
require_relative 'quicklinks_renderer'
|
8
|
+
|
9
|
+
I18n.enforce_available_locales = false
|
10
|
+
|
11
|
+
module Bookbinder
|
12
|
+
class Helpers < ::Middleman::Extension
|
13
|
+
# class << self
|
14
|
+
# def registered(app)
|
15
|
+
# app.helpers HelperMethods
|
16
|
+
# end
|
17
|
+
|
18
|
+
# alias :included :registered
|
19
|
+
# end
|
20
|
+
|
21
|
+
module HelperMethods
|
22
|
+
|
23
|
+
def yield_for_code_snippet(from: nil, at: nil)
|
24
|
+
cloner_factory = Ingest::ClonerFactory.new({out: $stdout},
|
25
|
+
LocalFilesystemAccessor.new,
|
26
|
+
Ingest::GitAccessor.new)
|
27
|
+
|
28
|
+
cloner = cloner_factory.produce(config[:local_repo_dir])
|
29
|
+
code_example_reader = CodeExampleReader.new({out: $stdout},
|
30
|
+
LocalFilesystemAccessor.new)
|
31
|
+
working_copy = cloner.call(source_repo_name: from,
|
32
|
+
source_ref: 'master',
|
33
|
+
destination_parent_dir: config[:workspace])
|
34
|
+
|
35
|
+
snippet, language = code_example_reader.get_snippet_and_language_at(at, working_copy)
|
36
|
+
|
37
|
+
delimiter = '```'
|
38
|
+
|
39
|
+
snippet.prepend("#{delimiter}#{language}\n").concat("\n#{delimiter}")
|
40
|
+
end
|
41
|
+
|
42
|
+
def elastic_search?
|
43
|
+
!!config[:elastic_search]
|
44
|
+
end
|
45
|
+
|
46
|
+
def yield_for_subnav
|
47
|
+
partial "subnavs/#{subnav_template_name}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def yield_for_archive_drop_down_menu
|
51
|
+
menu = ArchiveDropDownMenu.new(
|
52
|
+
config[:archive_menu],
|
53
|
+
current_path: current_page.path
|
54
|
+
)
|
55
|
+
unless menu.empty?
|
56
|
+
partial 'archive_menus/default', locals: { menu_title: menu.title,
|
57
|
+
dropdown_links: menu.dropdown_links }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def exclude_feedback
|
62
|
+
current_page.add_metadata({page: {feedback_disabled: true}})
|
63
|
+
end
|
64
|
+
|
65
|
+
def yield_for_feedback
|
66
|
+
partial 'layouts/feedback' if config[:feedback_enabled] && !current_page.metadata[:page][:feedback_disabled]
|
67
|
+
end
|
68
|
+
|
69
|
+
def exclude_repo_link
|
70
|
+
current_page.add_metadata({page: {repo_link_disabled: true}})
|
71
|
+
end
|
72
|
+
|
73
|
+
def render_repo_link
|
74
|
+
if config[:repo_link_enabled] && repo_url && !current_page.metadata[:page][:repo_link_disabled]
|
75
|
+
"<a id='repo-link' href='#{repo_url}'>Create a pull request or raise an issue on the source for this page in GitHub</a>"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def mermaid_diagram(&blk)
|
80
|
+
escaped_text = capture(&blk).gsub('-','\-')
|
81
|
+
|
82
|
+
@_out_buf.concat "<div class='mermaid'>#{escaped_text}</div>"
|
83
|
+
end
|
84
|
+
|
85
|
+
def modified_date(default_date: nil)
|
86
|
+
parsed_default_date = Time.parse(default_date).utc if default_date
|
87
|
+
|
88
|
+
date = page_last_modified_date || parsed_default_date
|
89
|
+
|
90
|
+
"Page last updated: <span data-behavior=\"DisplayModifiedDate\" data-modified-date=\"#{date.to_i}000\"></span>" if date
|
91
|
+
end
|
92
|
+
|
93
|
+
def breadcrumbs
|
94
|
+
page_chain = add_ancestors_of(current_page, [])
|
95
|
+
breadcrumbs = page_chain.map do |page|
|
96
|
+
make_breadcrumb(page, page == current_page)
|
97
|
+
end.compact
|
98
|
+
return if breadcrumbs.size < 2
|
99
|
+
return content_tag :ul, breadcrumbs.reverse.join(' '), class: 'breadcrumbs'
|
100
|
+
end
|
101
|
+
|
102
|
+
def vars
|
103
|
+
OpenStruct.new config[:template_variables]
|
104
|
+
end
|
105
|
+
|
106
|
+
def product_name
|
107
|
+
return vars.product_name
|
108
|
+
end
|
109
|
+
|
110
|
+
def product_name_long
|
111
|
+
return vars.product_name_long
|
112
|
+
end
|
113
|
+
|
114
|
+
def product_version
|
115
|
+
return vars.product_version
|
116
|
+
end
|
117
|
+
|
118
|
+
def set_title(*args)
|
119
|
+
current_page.data.title= args.join(' ')
|
120
|
+
end
|
121
|
+
|
122
|
+
def set_title_no_spaces(*args)
|
123
|
+
current_page.data.title= args.join
|
124
|
+
end
|
125
|
+
|
126
|
+
def product_info
|
127
|
+
config[:product_info].fetch(template_key, {})
|
128
|
+
end
|
129
|
+
|
130
|
+
def production_host
|
131
|
+
config[:production_host]
|
132
|
+
end
|
133
|
+
|
134
|
+
def quick_links
|
135
|
+
page_src = File.read(current_page.source_file)
|
136
|
+
quicklinks_renderer = QuicklinksRenderer.new(vars)
|
137
|
+
Redcarpet::Markdown.new(quicklinks_renderer).render(page_src)
|
138
|
+
end
|
139
|
+
|
140
|
+
def owners
|
141
|
+
html_resources = sitemap.resources.select { |r| r.path.end_with?('.html') }
|
142
|
+
html_resources.each.with_object({}) { |resource, owners|
|
143
|
+
owners[resource.path] = Array(resource.data['owner'])
|
144
|
+
}
|
145
|
+
end
|
146
|
+
|
147
|
+
def template_key
|
148
|
+
decreasingly_specific_namespaces.detect { |ns|
|
149
|
+
config[:subnav_templates].has_key?(ns)
|
150
|
+
}
|
151
|
+
end
|
152
|
+
|
153
|
+
def body_classes(path=current_path.dup, options={})
|
154
|
+
if path.is_a? Hash
|
155
|
+
options = path
|
156
|
+
path = current_path.dup
|
157
|
+
end
|
158
|
+
basename = File.basename(path)
|
159
|
+
dirname = File.dirname(path).gsub('.', '_')
|
160
|
+
page_classes(File.join(dirname, basename), options)
|
161
|
+
end
|
162
|
+
|
163
|
+
private
|
164
|
+
|
165
|
+
def subnav_template_name
|
166
|
+
config[:subnav_templates][template_key] || 'default'
|
167
|
+
end
|
168
|
+
|
169
|
+
def decreasingly_specific_namespaces
|
170
|
+
body_classes(numeric_prefix: numeric_class_prefix).
|
171
|
+
split(' ').reverse.drop(1).
|
172
|
+
map {|ns| ns.sub(/^#{numeric_class_prefix}/, '')}
|
173
|
+
end
|
174
|
+
|
175
|
+
def numeric_class_prefix
|
176
|
+
'NUMERIC_CLASS_PREFIX'
|
177
|
+
end
|
178
|
+
|
179
|
+
def page_last_modified_date
|
180
|
+
git_accessor = Ingest::GitAccessor.new
|
181
|
+
|
182
|
+
current_date = if current_page.data.dita
|
183
|
+
git_accessor.author_date(preprocessing_path(current_page.source_file), dita: true)
|
184
|
+
else
|
185
|
+
git_accessor.author_date(current_page.source_file)
|
186
|
+
end
|
187
|
+
|
188
|
+
current_date.utc if current_date
|
189
|
+
end
|
190
|
+
|
191
|
+
def repo_url
|
192
|
+
nested_dir, filename = parse_out_nested_dir_and_filename
|
193
|
+
|
194
|
+
repo_dir = match_repo_dir(nested_dir)
|
195
|
+
page_repo_config = config[:repo_links][repo_dir]
|
196
|
+
|
197
|
+
if page_repo_config && page_repo_config['ref']
|
198
|
+
org_repo = Pathname(page_repo_config['repo'])
|
199
|
+
ref = Pathname(page_repo_config['ref'])
|
200
|
+
at_path = at_path(page_repo_config)
|
201
|
+
nested_dir = extract_nested_directory(nested_dir, repo_dir)
|
202
|
+
|
203
|
+
"http://github.com/#{org_repo.join(Pathname('tree'), ref, Pathname(nested_dir), at_path, source_file(filename))}"
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def match_repo_dir(nested_dir)
|
208
|
+
config[:repo_links].keys
|
209
|
+
.select{ |key| nested_dir.match(/^#{key}/) }
|
210
|
+
.sort_by{ |key| key.length }
|
211
|
+
.last
|
212
|
+
end
|
213
|
+
|
214
|
+
def source_file(filename)
|
215
|
+
fs = LocalFilesystemAccessor.new
|
216
|
+
|
217
|
+
if current_page.data.dita
|
218
|
+
source_filename = "#{filename}.xml"
|
219
|
+
|
220
|
+
if fs.source_file_exists?(Pathname(preprocessing_path(current_page.source_file)).dirname,
|
221
|
+
source_filename)
|
222
|
+
source_filename
|
223
|
+
else
|
224
|
+
''
|
225
|
+
end
|
226
|
+
else
|
227
|
+
"#{filename}.html.md.erb"
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def preprocessing_path(current_source_path)
|
232
|
+
root_path, nested_repo_path = current_source_path.split('source')
|
233
|
+
|
234
|
+
root_path.gsub!('/output/master_middleman', '')
|
235
|
+
|
236
|
+
"#{root_path}output/preprocessing/sections#{nested_repo_path}"
|
237
|
+
end
|
238
|
+
|
239
|
+
def parse_out_nested_dir_and_filename
|
240
|
+
current_page.path
|
241
|
+
.match(/\/?(.*?)\/?([^\/]*)\.html$?/)
|
242
|
+
.captures
|
243
|
+
end
|
244
|
+
|
245
|
+
def extract_nested_directory(nested_dir, repo_dir)
|
246
|
+
nested_dir = nested_dir.gsub("#{repo_dir}", '')
|
247
|
+
nested_dir = nested_dir.sub('/', '') if nested_dir[0] == '/'
|
248
|
+
|
249
|
+
nested_dir
|
250
|
+
end
|
251
|
+
|
252
|
+
def at_path(page_repo_config)
|
253
|
+
path = page_repo_config['at_path'] || ""
|
254
|
+
|
255
|
+
Pathname(path)
|
256
|
+
end
|
257
|
+
|
258
|
+
def add_ancestors_of(page, ancestors)
|
259
|
+
if page
|
260
|
+
add_ancestors_of(page.parent, ancestors + [page])
|
261
|
+
else
|
262
|
+
ancestors
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
def make_breadcrumb(page, is_current_page)
|
267
|
+
return nil unless (text = page.data.breadcrumb || page.data.title)
|
268
|
+
if is_current_page
|
269
|
+
css_class = 'active'
|
270
|
+
link = content_tag :span, text
|
271
|
+
else
|
272
|
+
link = link_to(text, '/' + page.path)
|
273
|
+
end
|
274
|
+
content_tag :li, link, :class => css_class
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
helpers HelperMethods
|
279
|
+
|
280
|
+
end
|
281
|
+
end
|
282
|
+
::Middleman::Extensions.register(:bookbinder, Bookbinder::Helpers)
|