bookwatch 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bookwatch.gemspec +40 -0
- data/install_bin/bookwatch +5 -0
- data/lib/bookwatch/cli.rb +109 -0
- data/lib/bookwatch/code_example_reader.rb +95 -0
- data/lib/bookwatch/colorizer.rb +16 -0
- data/lib/bookwatch/commands/bind.rb +119 -0
- data/lib/bookwatch/commands/collection.rb +181 -0
- data/lib/bookwatch/commands/components/bind/directory_preparer.rb +33 -0
- data/lib/bookwatch/commands/components/bind/layout_preparer.rb +27 -0
- data/lib/bookwatch/commands/components/command_options.rb +45 -0
- data/lib/bookwatch/commands/components/imprint/directory_preparer.rb +24 -0
- data/lib/bookwatch/commands/generate.rb +92 -0
- data/lib/bookwatch/commands/imprint.rb +55 -0
- data/lib/bookwatch/commands/punch.rb +33 -0
- data/lib/bookwatch/commands/update_local_doc_repos.rb +42 -0
- data/lib/bookwatch/commands/watch.rb +100 -0
- data/lib/bookwatch/config/checkers/archive_menu_checker.rb +29 -0
- data/lib/bookwatch/config/checkers/ditamap_presence_checker.rb +27 -0
- data/lib/bookwatch/config/checkers/duplicate_section_name_checker.rb +33 -0
- data/lib/bookwatch/config/checkers/products_checker.rb +34 -0
- data/lib/bookwatch/config/checkers/repository_name_presence_checker.rb +34 -0
- data/lib/bookwatch/config/checkers/required_keys_checker.rb +18 -0
- data/lib/bookwatch/config/checkers/section_presence_checker.rb +15 -0
- data/lib/bookwatch/config/configuration.rb +119 -0
- data/lib/bookwatch/config/configuration_decorator.rb +54 -0
- data/lib/bookwatch/config/dita_config_generator.rb +61 -0
- data/lib/bookwatch/config/fetcher.rb +64 -0
- data/lib/bookwatch/config/imprint/configuration.rb +24 -0
- data/lib/bookwatch/config/product_config.rb +34 -0
- data/lib/bookwatch/config/section_config.rb +85 -0
- data/lib/bookwatch/config/validator.rb +33 -0
- data/lib/bookwatch/config/yaml_loader.rb +34 -0
- data/lib/bookwatch/css_link_checker.rb +67 -0
- data/lib/bookwatch/directory_helpers.rb +15 -0
- data/lib/bookwatch/dita_command_creator.rb +95 -0
- data/lib/bookwatch/dita_html_for_middleman_formatter.rb +45 -0
- data/lib/bookwatch/errors/programmer_mistake.rb +5 -0
- data/lib/bookwatch/html_document_manipulator.rb +21 -0
- data/lib/bookwatch/ingest/cloner_factory.rb +26 -0
- data/lib/bookwatch/ingest/destination_directory.rb +21 -0
- data/lib/bookwatch/ingest/git_accessor.rb +102 -0
- data/lib/bookwatch/ingest/git_cloner.rb +36 -0
- data/lib/bookwatch/ingest/local_filesystem_cloner.rb +66 -0
- data/lib/bookwatch/ingest/missing_working_copy.rb +27 -0
- data/lib/bookwatch/ingest/repo_identifier.rb +45 -0
- data/lib/bookwatch/ingest/section_repository.rb +49 -0
- data/lib/bookwatch/ingest/update_failure.rb +15 -0
- data/lib/bookwatch/ingest/update_success.rb +12 -0
- data/lib/bookwatch/ingest/working_copy.rb +36 -0
- data/lib/bookwatch/local_filesystem_accessor.rb +122 -0
- data/lib/bookwatch/middleman_runner.rb +48 -0
- data/lib/bookwatch/postprocessing/link_checker.rb +125 -0
- data/lib/bookwatch/postprocessing/redirection.rb +38 -0
- data/lib/bookwatch/preprocessing/dita_html_preprocessor.rb +91 -0
- data/lib/bookwatch/preprocessing/dita_pdf_preprocessor.rb +48 -0
- data/lib/bookwatch/preprocessing/link_to_site_gen_dir.rb +39 -0
- data/lib/bookwatch/preprocessing/preprocessor.rb +26 -0
- data/lib/bookwatch/server_director.rb +30 -0
- data/lib/bookwatch/sheller.rb +52 -0
- data/lib/bookwatch/streams/colorized_stream.rb +25 -0
- data/lib/bookwatch/streams/filter_stream.rb +22 -0
- data/lib/bookwatch/subnav/navigation_entries_from_html_toc.rb +59 -0
- data/lib/bookwatch/subnav/navigation_entries_from_markdown_root.rb +116 -0
- data/lib/bookwatch/subnav/pdf_config_creator.rb +50 -0
- data/lib/bookwatch/subnav/subnav_generator.rb +28 -0
- data/lib/bookwatch/subnav/subnav_generator_factory.rb +29 -0
- data/lib/bookwatch/subnav/template_creator.rb +71 -0
- data/lib/bookwatch/terminal.rb +19 -0
- data/lib/bookwatch/values/output_locations.rb +91 -0
- data/lib/bookwatch/values/product_info.rb +11 -0
- data/lib/bookwatch/values/section.rb +58 -0
- data/lib/bookwatch/values/subnav_template.rb +4 -0
- data/lib/bookwatch/values/user_message.rb +15 -0
- data/master_middleman/archive_drop_down_menu.rb +50 -0
- data/master_middleman/bookwatch_helpers.rb +259 -0
- data/master_middleman/compass_runner.rb +0 -0
- data/master_middleman/config.rb +34 -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/bookwatch.js +103 -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 +69 -0
- data/master_middleman/source/stylesheets/all.css.scss +3 -0
- data/master_middleman/source/stylesheets/base.scss +380 -0
- data/master_middleman/source/stylesheets/book-styles.css.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 +300 -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.css.scss +58 -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 +47 -0
- data/template_app/Gemfile +10 -0
- data/template_app/Gemfile.lock +43 -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 +47 -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 +29 -0
- data/template_app/lib/server.rb +52 -0
- data/template_app/mail_sender.rb +69 -0
- data/template_app/rack_app.rb +110 -0
- data/template_app/search-results.html.erb +75 -0
- data/template_app/search.yml +22 -0
- metadata +491 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
module Bookwatch
|
2
|
+
module Config
|
3
|
+
module Checkers
|
4
|
+
class ArchiveMenuChecker
|
5
|
+
MissingArchiveMenuPartialError = Class.new(RuntimeError)
|
6
|
+
ArchiveMenuNotDefinedError = Class.new(RuntimeError)
|
7
|
+
EmptyArchiveItemsError = Class.new(RuntimeError)
|
8
|
+
|
9
|
+
def initialize(file_system_accessor)
|
10
|
+
@file_system_accessor = file_system_accessor
|
11
|
+
end
|
12
|
+
|
13
|
+
def check(config)
|
14
|
+
partial_location = './master_middleman/source/archive_menus/_default.erb'
|
15
|
+
if config.archive_menu && config.archive_menu.include?(nil)
|
16
|
+
EmptyArchiveItemsError.new 'Did you forget to add a value to the archive_menu?'
|
17
|
+
elsif config.archive_menu && !file_system_accessor.file_exist?(partial_location)
|
18
|
+
MissingArchiveMenuPartialError.new "You must provide a template partial named at #{partial_location}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
attr_reader :file_system_accessor
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Bookwatch
|
2
|
+
module Config
|
3
|
+
module Checkers
|
4
|
+
class DitamapPresenceChecker
|
5
|
+
DitamapLocationError = Class.new(RuntimeError)
|
6
|
+
|
7
|
+
def check(config)
|
8
|
+
if any_sections_missing_ditamaps?(config.sections)
|
9
|
+
DitamapLocationError.new(
|
10
|
+
"You must have a 'ditamap_location' for each key in dita_sections."
|
11
|
+
)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def any_sections_missing_ditamaps?(sections)
|
18
|
+
sections.any? do |s|
|
19
|
+
if s.preprocessor_config.has_key?('ditamap_location')
|
20
|
+
s.preprocessor_config['ditamap_location'].nil? || s.preprocessor_config['ditamap_location'].empty?
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require_relative '../../ingest/destination_directory'
|
2
|
+
|
3
|
+
module Bookwatch
|
4
|
+
module Config
|
5
|
+
module Checkers
|
6
|
+
class DuplicateSectionNameChecker
|
7
|
+
DuplicateSectionNameError = Class.new(RuntimeError)
|
8
|
+
|
9
|
+
def check(config)
|
10
|
+
if duplicate_section_names?(config)
|
11
|
+
DuplicateSectionNameError.new error_message
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def duplicate_section_names?(config)
|
18
|
+
directory_names = config.sections.map {|section|
|
19
|
+
Ingest::DestinationDirectory.new(section.repo_name,
|
20
|
+
section.desired_directory_name)
|
21
|
+
}
|
22
|
+
directory_names.length != directory_names.uniq.length
|
23
|
+
end
|
24
|
+
|
25
|
+
def error_message
|
26
|
+
<<-ERROR
|
27
|
+
Duplicate repository names are not allowed.
|
28
|
+
ERROR
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Bookwatch
|
2
|
+
module Config
|
3
|
+
module Checkers
|
4
|
+
class ProductsChecker
|
5
|
+
MissingProductsKeyError = Class.new(RuntimeError)
|
6
|
+
MissingProductIdError = Class.new(RuntimeError)
|
7
|
+
|
8
|
+
def check(config)
|
9
|
+
@config = config
|
10
|
+
|
11
|
+
if section_product_ids.count > 0
|
12
|
+
if config.products.empty?
|
13
|
+
MissingProductsKeyError.new('You must specify at least one product under the products key in config.yml')
|
14
|
+
elsif missing_products.count != 0
|
15
|
+
MissingProductIdError.new("Your config.yml is missing required product id under the products key. Required product ids are #{missing_products.join(", ")}.")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :config
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def missing_products
|
25
|
+
section_product_ids - config.products.map(&:id)
|
26
|
+
end
|
27
|
+
|
28
|
+
def section_product_ids
|
29
|
+
config.sections.map(&:product_id).compact.uniq
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Bookwatch
|
2
|
+
module Config
|
3
|
+
module Checkers
|
4
|
+
class RepositoryNamePresenceChecker
|
5
|
+
MissingRepositoryNameError = Class.new(RuntimeError)
|
6
|
+
|
7
|
+
def check(config)
|
8
|
+
failures = config.sections.reject do |section|
|
9
|
+
section.repo_name
|
10
|
+
end
|
11
|
+
|
12
|
+
if failures.empty?
|
13
|
+
nil
|
14
|
+
else
|
15
|
+
MissingRepositoryNameError.new error_message
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def error_message
|
22
|
+
<<-ERROR
|
23
|
+
Cannot locate a specific section.
|
24
|
+
All sections must provide the section 'name' key under the 'repository' key:
|
25
|
+
|
26
|
+
sections:
|
27
|
+
- repository:
|
28
|
+
name: 'your-org/your-repo'
|
29
|
+
ERROR
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative '../configuration'
|
2
|
+
|
3
|
+
module Bookwatch
|
4
|
+
module Config
|
5
|
+
module Checkers
|
6
|
+
class RequiredKeysChecker
|
7
|
+
MissingRequiredKeyError = Class.new(RuntimeError)
|
8
|
+
|
9
|
+
def check(config)
|
10
|
+
missing_keys = Config::Configuration::CONFIG_REQUIRED_KEYS.reject { |key| config.has_option?(key) }
|
11
|
+
if missing_keys.any?
|
12
|
+
MissingRequiredKeyError.new("Your config.yml is missing required key(s). Required keys are #{missing_keys.join(", ")}.")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Bookwatch
|
2
|
+
module Config
|
3
|
+
module Checkers
|
4
|
+
class SectionPresenceChecker
|
5
|
+
NoSectionsError = Class.new(RuntimeError)
|
6
|
+
|
7
|
+
def check(config)
|
8
|
+
if config.sections.none?
|
9
|
+
NoSectionsError.new('No sections found in your config.yml. Add sections under the appropriate key(s) and try again.')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require_relative '../../../lib/bookwatch/config/dita_config_generator'
|
2
|
+
require_relative '../ingest/destination_directory'
|
3
|
+
require_relative '../ingest/repo_identifier'
|
4
|
+
require_relative 'section_config'
|
5
|
+
require_relative 'product_config'
|
6
|
+
|
7
|
+
module Bookwatch
|
8
|
+
module Config
|
9
|
+
class Configuration
|
10
|
+
class << self
|
11
|
+
def parse(input_config)
|
12
|
+
section_configs = to_section_configs(combined_sections(input_config))
|
13
|
+
parse_sections(input_config, section_configs)
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
|
18
|
+
def parse_sections(input_config, section_configs)
|
19
|
+
new(symbolize_keys(input_config).
|
20
|
+
merge(expand_repo_identifiers(input_config)).
|
21
|
+
merge(sections: section_configs))
|
22
|
+
end
|
23
|
+
|
24
|
+
def symbolize_keys(h)
|
25
|
+
h.reduce({}) {|acc, (k, v)| acc.merge(k.to_sym => v) }
|
26
|
+
end
|
27
|
+
|
28
|
+
def expand_repo_identifiers(input_config)
|
29
|
+
input_config.select {|k, _| k.match(/_repo$/)}.
|
30
|
+
reduce({}) {|h, (k, v)| h.merge(:"#{k}_url" => Ingest::RepoIdentifier.new(v))}
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_section_configs sections
|
34
|
+
sections.map { |section| Config::SectionConfig.new(section) }
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def combined_sections(input_config)
|
40
|
+
regular_sections(input_config) + dita_sections(input_config)
|
41
|
+
end
|
42
|
+
|
43
|
+
def regular_sections(input_config)
|
44
|
+
input_config['sections'] || []
|
45
|
+
end
|
46
|
+
|
47
|
+
def dita_sections(input_config)
|
48
|
+
(input_config['dita_sections'] || []).map { |dita_section|
|
49
|
+
DitaConfigGenerator.new(dita_section).to_hash
|
50
|
+
}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def initialize(config)
|
55
|
+
@config = config
|
56
|
+
@products = assemble_products || []
|
57
|
+
end
|
58
|
+
|
59
|
+
CONFIG_REQUIRED_KEYS = %w(book_repo public_host)
|
60
|
+
CONFIG_OPTIONAL_KEYS = %w(archive_menu book_repo_url cred_repo cred_repo_url repo_link_enabled repo_links feedback_enabled layout_repo layout_repo_ref layout_repo_url sections)
|
61
|
+
|
62
|
+
CONFIG_REQUIRED_KEYS.each do |method_name|
|
63
|
+
define_method(method_name) do
|
64
|
+
config.fetch(method_name.to_sym)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
CONFIG_OPTIONAL_KEYS.each do |method_name|
|
69
|
+
define_method(method_name) do
|
70
|
+
config[method_name.to_sym]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def broken_link_exclusions
|
75
|
+
config.fetch(:broken_link_exclusions, /(?!.*)/)
|
76
|
+
end
|
77
|
+
|
78
|
+
def template_variables
|
79
|
+
config.fetch(:template_variables, {})
|
80
|
+
end
|
81
|
+
|
82
|
+
def merge(other_configuration)
|
83
|
+
Configuration.new(config.merge(other_configuration.instance_variable_get(:@config)))
|
84
|
+
end
|
85
|
+
|
86
|
+
def merge_sections(incoming_sections)
|
87
|
+
merge(Configuration.new(sections: sections + incoming_sections))
|
88
|
+
end
|
89
|
+
|
90
|
+
def has_option?(key)
|
91
|
+
!!config[key.to_sym]
|
92
|
+
end
|
93
|
+
|
94
|
+
def elastic_search?
|
95
|
+
config.fetch(:elastic_search, false)
|
96
|
+
end
|
97
|
+
|
98
|
+
def ==(o)
|
99
|
+
o.class == self.class && o.instance_variable_get(:@config) == @config
|
100
|
+
end
|
101
|
+
|
102
|
+
alias_method :eql?, :==
|
103
|
+
|
104
|
+
attr_reader :products
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def assemble_products
|
109
|
+
if config[:products]
|
110
|
+
config[:products].map do |product|
|
111
|
+
Config::ProductConfig.new(product)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
attr_reader :config
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require_relative 'configuration'
|
2
|
+
|
3
|
+
module Bookwatch
|
4
|
+
module Config
|
5
|
+
class ConfigurationDecorator
|
6
|
+
def initialize(loader: nil, config_filename: nil)
|
7
|
+
@loader = loader
|
8
|
+
@config_filename = config_filename
|
9
|
+
end
|
10
|
+
|
11
|
+
def generate(base_config, sections)
|
12
|
+
base_config.merge(
|
13
|
+
Configuration.new(
|
14
|
+
repo_links: repo_link_config(base_config, sections),
|
15
|
+
archive_menu: root_config(base_config).merge(section_config(sections)))
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
attr_reader :loader, :config_filename
|
22
|
+
|
23
|
+
def repo_link_config(base_config, sections)
|
24
|
+
if base_config.repo_link_enabled
|
25
|
+
sections.reduce({}) {|config, section|
|
26
|
+
config.merge(
|
27
|
+
section.destination_directory.to_s => {
|
28
|
+
'repo' => section.repo_name,
|
29
|
+
'ref' => section.source_ref,
|
30
|
+
'at_path' => section.at_repo_path
|
31
|
+
}
|
32
|
+
)
|
33
|
+
}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def root_config(base_config)
|
38
|
+
{ '.' => base_config.archive_menu }
|
39
|
+
end
|
40
|
+
|
41
|
+
def section_config(sections)
|
42
|
+
sections.reduce({}) {|config, section|
|
43
|
+
config_path = section.path_to_repo_dir.join(config_filename)
|
44
|
+
archive_config = loader.load_key(config_path, 'archive_menu')
|
45
|
+
if archive_config
|
46
|
+
config.merge(section.desired_directory_name => archive_config)
|
47
|
+
else
|
48
|
+
config
|
49
|
+
end
|
50
|
+
}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require_relative '../../../lib/bookwatch/ingest/destination_directory'
|
2
|
+
|
3
|
+
module Bookwatch
|
4
|
+
module Config
|
5
|
+
class DitaConfigGenerator
|
6
|
+
|
7
|
+
def initialize(section_hash)
|
8
|
+
@section_hash = section_hash
|
9
|
+
end
|
10
|
+
|
11
|
+
def subnav_template
|
12
|
+
dest_dir = Ingest::DestinationDirectory.new(section_hash.fetch('repository', {})['name'], section_hash['directory'])
|
13
|
+
|
14
|
+
"dita_subnav_#{dest_dir}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def ditamap_location
|
18
|
+
section_hash['ditamap_location'] if section_hash['ditamap_location'] && !section_hash['ditamap_location'].empty?
|
19
|
+
end
|
20
|
+
|
21
|
+
def pdf_output_filename
|
22
|
+
if present?(section_hash['output_filename'])
|
23
|
+
filename = section_hash['output_filename']
|
24
|
+
elsif ditamap_location
|
25
|
+
filename = ditamap_location.gsub(/\.ditamap/, '')
|
26
|
+
else
|
27
|
+
return
|
28
|
+
end
|
29
|
+
|
30
|
+
filename + '.pdf'
|
31
|
+
end
|
32
|
+
|
33
|
+
def preprocessor_config
|
34
|
+
{
|
35
|
+
'preprocessor_config' => {
|
36
|
+
'ditamap_location' => ditamap_location,
|
37
|
+
'ditaval_location' => section_hash['ditaval_location']
|
38
|
+
}
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_hash
|
43
|
+
section_hash.tap do |hash|
|
44
|
+
hash.merge!(preprocessor_config)
|
45
|
+
.merge!('subnav_template' => subnav_template, 'output_filename' => pdf_output_filename)
|
46
|
+
|
47
|
+
hash.delete('ditaval_location')
|
48
|
+
hash.delete('ditamap_location')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
attr_reader :section_hash
|
55
|
+
|
56
|
+
def present?(value)
|
57
|
+
value && !value.empty?
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require_relative 'configuration'
|
2
|
+
require_relative 'yaml_loader'
|
3
|
+
|
4
|
+
module Bookwatch
|
5
|
+
module Config
|
6
|
+
class Fetcher
|
7
|
+
def initialize(configuration_validator, loader, config_class)
|
8
|
+
@loader = loader
|
9
|
+
@configuration_validator = configuration_validator
|
10
|
+
@config_class = config_class
|
11
|
+
end
|
12
|
+
|
13
|
+
def fetch_config
|
14
|
+
@base_config ||= read_config_file
|
15
|
+
@optional_configs ||= read_optional_configs
|
16
|
+
|
17
|
+
@config ||= validate(@base_config, @optional_configs)
|
18
|
+
end
|
19
|
+
|
20
|
+
def set_config_dir_path(config_dir_path)
|
21
|
+
@config_dir_path = File.expand_path(config_dir_path)
|
22
|
+
end
|
23
|
+
|
24
|
+
def set_config_file_path(config_file_path)
|
25
|
+
@config_file_path = File.expand_path(config_file_path)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
attr_reader(:loader, :configuration_validator, :config, :config_file_path, :config_dir_path,
|
31
|
+
:config_class)
|
32
|
+
|
33
|
+
def read_config_file
|
34
|
+
loader.load(config_file_path)
|
35
|
+
|
36
|
+
rescue FileNotFoundError => e
|
37
|
+
raise "The configuration file specified does not exist. Please create a config #{e} file at #{config_file_path} and try again."
|
38
|
+
rescue InvalidSyntaxError => e
|
39
|
+
raise syntax_error(e)
|
40
|
+
end
|
41
|
+
|
42
|
+
def read_optional_configs
|
43
|
+
Dir["#{config_dir_path}/*.yml"].map do |config_file|
|
44
|
+
loader.load(File.expand_path(config_file)) || {}
|
45
|
+
end.reduce({}, :merge)
|
46
|
+
rescue InvalidSyntaxError => e
|
47
|
+
raise syntax_error(e)
|
48
|
+
end
|
49
|
+
|
50
|
+
def validate(base_hash, optional_hash)
|
51
|
+
raise 'Your config.yml appears to be empty. Please check and try again.' unless base_hash
|
52
|
+
|
53
|
+
config_class.parse(base_hash.merge(optional_hash)).tap do |config|
|
54
|
+
errors = configuration_validator.exceptions(config)
|
55
|
+
raise errors.first if errors.any?
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def syntax_error(e)
|
60
|
+
"There is a syntax error in your config file: \n #{e}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|