alb-test 10.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. checksums.yaml +7 -0
  2. data/bookbinder.gemspec +46 -0
  3. data/install_bin/bookbinder +5 -0
  4. data/lib/bookbinder/cli.rb +105 -0
  5. data/lib/bookbinder/code_example_reader.rb +95 -0
  6. data/lib/bookbinder/colorizer.rb +16 -0
  7. data/lib/bookbinder/commands/bind.rb +120 -0
  8. data/lib/bookbinder/commands/collection.rb +181 -0
  9. data/lib/bookbinder/commands/components/bind/directory_preparer.rb +33 -0
  10. data/lib/bookbinder/commands/components/bind/layout_preparer.rb +27 -0
  11. data/lib/bookbinder/commands/components/command_options.rb +45 -0
  12. data/lib/bookbinder/commands/components/imprint/directory_preparer.rb +24 -0
  13. data/lib/bookbinder/commands/generate.rb +92 -0
  14. data/lib/bookbinder/commands/imprint.rb +55 -0
  15. data/lib/bookbinder/commands/punch.rb +33 -0
  16. data/lib/bookbinder/commands/update_local_doc_repos.rb +42 -0
  17. data/lib/bookbinder/commands/watch.rb +100 -0
  18. data/lib/bookbinder/config/checkers/archive_menu_checker.rb +29 -0
  19. data/lib/bookbinder/config/checkers/ditamap_presence_checker.rb +27 -0
  20. data/lib/bookbinder/config/checkers/duplicate_section_name_checker.rb +33 -0
  21. data/lib/bookbinder/config/checkers/products_checker.rb +34 -0
  22. data/lib/bookbinder/config/checkers/repository_name_presence_checker.rb +34 -0
  23. data/lib/bookbinder/config/checkers/required_keys_checker.rb +18 -0
  24. data/lib/bookbinder/config/checkers/section_presence_checker.rb +15 -0
  25. data/lib/bookbinder/config/configuration.rb +119 -0
  26. data/lib/bookbinder/config/configuration_decorator.rb +54 -0
  27. data/lib/bookbinder/config/dita_config_generator.rb +61 -0
  28. data/lib/bookbinder/config/fetcher.rb +64 -0
  29. data/lib/bookbinder/config/imprint/configuration.rb +24 -0
  30. data/lib/bookbinder/config/product_config.rb +34 -0
  31. data/lib/bookbinder/config/section_config.rb +85 -0
  32. data/lib/bookbinder/config/validator.rb +33 -0
  33. data/lib/bookbinder/config/yaml_loader.rb +34 -0
  34. data/lib/bookbinder/css_link_checker.rb +67 -0
  35. data/lib/bookbinder/directory_helpers.rb +15 -0
  36. data/lib/bookbinder/dita_command_creator.rb +95 -0
  37. data/lib/bookbinder/dita_html_for_middleman_formatter.rb +45 -0
  38. data/lib/bookbinder/errors/programmer_mistake.rb +5 -0
  39. data/lib/bookbinder/html_document_manipulator.rb +21 -0
  40. data/lib/bookbinder/ingest/cloner_factory.rb +26 -0
  41. data/lib/bookbinder/ingest/destination_directory.rb +21 -0
  42. data/lib/bookbinder/ingest/git_accessor.rb +102 -0
  43. data/lib/bookbinder/ingest/git_cloner.rb +36 -0
  44. data/lib/bookbinder/ingest/local_filesystem_cloner.rb +66 -0
  45. data/lib/bookbinder/ingest/missing_working_copy.rb +27 -0
  46. data/lib/bookbinder/ingest/repo_identifier.rb +45 -0
  47. data/lib/bookbinder/ingest/section_repository.rb +49 -0
  48. data/lib/bookbinder/ingest/update_failure.rb +15 -0
  49. data/lib/bookbinder/ingest/update_success.rb +12 -0
  50. data/lib/bookbinder/ingest/working_copy.rb +36 -0
  51. data/lib/bookbinder/local_filesystem_accessor.rb +122 -0
  52. data/lib/bookbinder/middleman_runner.rb +50 -0
  53. data/lib/bookbinder/postprocessing/link_checker.rb +125 -0
  54. data/lib/bookbinder/postprocessing/redirection.rb +38 -0
  55. data/lib/bookbinder/preprocessing/dita_html_preprocessor.rb +91 -0
  56. data/lib/bookbinder/preprocessing/dita_pdf_preprocessor.rb +48 -0
  57. data/lib/bookbinder/preprocessing/link_to_site_gen_dir.rb +39 -0
  58. data/lib/bookbinder/preprocessing/preprocessor.rb +26 -0
  59. data/lib/bookbinder/server_director.rb +30 -0
  60. data/lib/bookbinder/sheller.rb +52 -0
  61. data/lib/bookbinder/streams/colorized_stream.rb +25 -0
  62. data/lib/bookbinder/streams/filter_stream.rb +22 -0
  63. data/lib/bookbinder/subnav/navigation_entries_from_html_toc.rb +59 -0
  64. data/lib/bookbinder/subnav/navigation_entries_from_markdown_root.rb +116 -0
  65. data/lib/bookbinder/subnav/pdf_config_creator.rb +50 -0
  66. data/lib/bookbinder/subnav/subnav_generator.rb +28 -0
  67. data/lib/bookbinder/subnav/subnav_generator_factory.rb +29 -0
  68. data/lib/bookbinder/subnav/template_creator.rb +71 -0
  69. data/lib/bookbinder/terminal.rb +19 -0
  70. data/lib/bookbinder/values/output_locations.rb +91 -0
  71. data/lib/bookbinder/values/product_info.rb +11 -0
  72. data/lib/bookbinder/values/section.rb +58 -0
  73. data/lib/bookbinder/values/subnav_template.rb +4 -0
  74. data/lib/bookbinder/values/user_message.rb +15 -0
  75. data/master_middleman/archive_drop_down_menu.rb +50 -0
  76. data/master_middleman/bookbinder_helpers.rb +282 -0
  77. data/master_middleman/compass_runner.rb +0 -0
  78. data/master_middleman/config.rb +45 -0
  79. data/master_middleman/proof.rb +90 -0
  80. data/master_middleman/quicklinks_renderer.rb +80 -0
  81. data/master_middleman/source/javascripts/all.js +2 -0
  82. data/master_middleman/source/javascripts/book.js +1 -0
  83. data/master_middleman/source/javascripts/bookbinder.js +130 -0
  84. data/master_middleman/source/layouts/_additional-scripts.erb +0 -0
  85. data/master_middleman/source/layouts/_book-footer.erb +0 -0
  86. data/master_middleman/source/layouts/_book-search.erb +0 -0
  87. data/master_middleman/source/layouts/_book-title.erb +3 -0
  88. data/master_middleman/source/layouts/_header.erb +34 -0
  89. data/master_middleman/source/layouts/_local-header.erb +0 -0
  90. data/master_middleman/source/layouts/_page-footer.erb +1 -0
  91. data/master_middleman/source/layouts/_title.erb +5 -0
  92. data/master_middleman/source/layouts/layout.erb +70 -0
  93. data/master_middleman/source/stylesheets/all.css.scss +3 -0
  94. data/master_middleman/source/stylesheets/base.scss +324 -0
  95. data/master_middleman/source/stylesheets/book-styles.scss +0 -0
  96. data/master_middleman/source/stylesheets/layout-styles.scss +0 -0
  97. data/master_middleman/source/stylesheets/partials/_book-base-values.scss +0 -0
  98. data/master_middleman/source/stylesheets/partials/_book-vars.scss +0 -0
  99. data/master_middleman/source/stylesheets/partials/_default.scss +302 -0
  100. data/master_middleman/source/stylesheets/partials/_footer.scss +64 -0
  101. data/master_middleman/source/stylesheets/partials/_header.scss +419 -0
  102. data/master_middleman/source/stylesheets/partials/_layout-vars.scss +0 -0
  103. data/master_middleman/source/stylesheets/partials/_mixins.scss +53 -0
  104. data/master_middleman/source/stylesheets/partials/_reset.scss +233 -0
  105. data/master_middleman/source/stylesheets/partials/_search.scss +78 -0
  106. data/master_middleman/source/stylesheets/partials/_sidenav.scss +191 -0
  107. data/master_middleman/source/stylesheets/partials/_syntax-highlight.scss +64 -0
  108. data/master_middleman/source/stylesheets/partials/_vars.scss +64 -0
  109. data/master_middleman/source/stylesheets/print-book-styles.scss +0 -0
  110. data/master_middleman/source/stylesheets/print-layout-styles.scss +0 -0
  111. data/master_middleman/source/stylesheets/print.css.scss +57 -0
  112. data/master_middleman/source/subnavs/_default.erb +0 -0
  113. data/master_middleman/source/subnavs/_nav-links.erb +10 -0
  114. data/master_middleman/source/subnavs/_subnav_template.erb +8 -0
  115. data/master_middleman/subdirectory_aware_assets.rb +36 -0
  116. data/template_app/Gemfile +10 -0
  117. data/template_app/Gemfile.lock +49 -0
  118. data/template_app/config.ru +9 -0
  119. data/template_app/lib/rack_static_if_exists.rb +19 -0
  120. data/template_app/lib/search/handler.rb +73 -0
  121. data/template_app/lib/search/hit.rb +21 -0
  122. data/template_app/lib/search/query.rb +74 -0
  123. data/template_app/lib/search/renderer.rb +30 -0
  124. data/template_app/lib/server.rb +52 -0
  125. data/template_app/mail_sender.rb +61 -0
  126. data/template_app/rack_app.rb +110 -0
  127. data/template_app/search-results.html.erb +81 -0
  128. data/template_app/search.yml +23 -0
  129. metadata +548 -0
@@ -0,0 +1,122 @@
1
+ require 'find'
2
+ require 'pathname'
3
+ require_relative 'errors/programmer_mistake'
4
+
5
+ module Bookbinder
6
+
7
+ class LocalFilesystemAccessor
8
+ def file_exist?(path)
9
+ File.exist?(path)
10
+ end
11
+
12
+ def is_file?(path)
13
+ File.file?(path)
14
+ end
15
+
16
+ def is_dir?(path)
17
+ Dir.exists?(path)
18
+ end
19
+
20
+ def write(to: nil, text: nil)
21
+ make_directory(File.dirname to)
22
+
23
+ File.open(to, 'a') do |f|
24
+ f.write(text)
25
+ end
26
+
27
+ to
28
+ end
29
+
30
+ def overwrite(to: nil, text: nil)
31
+ File.delete(to) if file_exist?(to)
32
+ write(to: to, text: text)
33
+ end
34
+
35
+ def read(path)
36
+ File.read(path)
37
+ end
38
+
39
+ def empty_directory(path)
40
+ FileUtils.rm_rf(File.join(path, '.'))
41
+ end
42
+
43
+ def remove_directory(path)
44
+ FileUtils.rm_rf(path)
45
+ end
46
+
47
+ def make_directory(path)
48
+ FileUtils.mkdir_p(path)
49
+ end
50
+
51
+ def copy(src, dest)
52
+ make_directory(dest)
53
+ FileUtils.cp_r src, dest
54
+ end
55
+
56
+ def copy_and_rename(src, dest)
57
+ make_directory(Pathname(dest).dirname)
58
+ FileUtils.cp_r src, dest
59
+ end
60
+
61
+ def copy_contents(src, dest)
62
+ raise Errors::ProgrammerMistake.new("The method copy_contents cannot copy the contents of the directory '#{src}' because it was not found.") unless Dir.exists?(src)
63
+ copy "#{src}/.", dest
64
+ end
65
+
66
+ def copy_including_intermediate_dirs(file, root, dest)
67
+ path_within_destination = relative_path_from(root, file)
68
+ extended_dest = File.dirname(File.join dest, path_within_destination)
69
+ copy file, extended_dest
70
+ end
71
+
72
+ def link_creating_intermediate_dirs(src, dst)
73
+ FileUtils.mkdir_p(File.dirname(dst))
74
+ File.symlink(src, dst)
75
+ end
76
+
77
+ def rename_file(path, new_name)
78
+ new_path = File.expand_path File.join path, '..', new_name
79
+ File.rename(path, new_path)
80
+ end
81
+
82
+ def find_files_with_ext(ext, path)
83
+ all_files = find_files_recursively(path)
84
+ matching_files = all_files.select {|p| p.to_s.match(/\.#{ext}/) }
85
+ matching_files.map(&:to_s)
86
+ end
87
+
88
+ def relative_path_from(src, target)
89
+ target_path = Pathname(File.absolute_path target)
90
+ relative_path = target_path.relative_path_from(Pathname(File.absolute_path src))
91
+ relative_path.to_s
92
+ end
93
+
94
+ def find_files_recursively(from)
95
+ `find -L #{from} -type f`.
96
+ lines.
97
+ map(&:chomp).
98
+ map(&Pathname.method(:new)).
99
+ reject {|p| p.to_s.match %r{/\.}}.
100
+ reject(&:directory?)
101
+ end
102
+
103
+ def find_files_extension_agnostically(pattern, directory='.')
104
+ extensionless_pattern = File.join(File.dirname(pattern), File.basename(pattern).split('.').first)
105
+
106
+ `find -L #{directory} -path '#{directory}/#{extensionless_pattern}.*' -type f`.
107
+ lines.
108
+ map(&:chomp).
109
+ map(&Pathname.method(:new))
110
+ end
111
+
112
+ def source_file_exists?(directory, path_to_file)
113
+ path = Pathname(path_to_file.split('/').last)
114
+ source_file_found = false
115
+
116
+ Pathname(directory).ascend do |dir|
117
+ source_file_found = true if dir.entries.any? { |entry| entry == path }
118
+ end
119
+ source_file_found
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,50 @@
1
+ require 'middleman-core'
2
+ require 'middleman-core/cli'
3
+ require 'middleman-core/profiling'
4
+ require 'yaml'
5
+
6
+ module Bookbinder
7
+ class MiddlemanRunner
8
+ def initialize(fs, sheller)
9
+ @fs = fs
10
+ @sheller = sheller
11
+ end
12
+
13
+ def run(command,
14
+ streams: nil,
15
+ output_locations: nil,
16
+ config: nil,
17
+ local_repo_dir: nil,
18
+ subnavs: nil,
19
+ product_info: nil,
20
+ proof: false)
21
+ streams[:out].puts "\nRunning middleman...\n\n"
22
+ Dir.chdir(output_locations.master_dir) do
23
+ config = {
24
+ archive_menu: config.archive_menu,
25
+ production_host: config.public_host,
26
+ subnav_templates: subnavs,
27
+ template_variables: config.template_variables,
28
+ local_repo_dir: local_repo_dir,
29
+ workspace: output_locations.workspace_dir,
30
+ feedback_enabled: config.feedback_enabled,
31
+ repo_link_enabled: config.repo_link_enabled,
32
+ repo_links: config.repo_links,
33
+ product_info: product_info,
34
+ elastic_search: config.elastic_search?,
35
+ proof: proof
36
+ }
37
+
38
+ fs.write(to: "bookbinder_config.yml", text: YAML.dump(config))
39
+ sheller.run_command({'MM_ROOT' => output_locations.master_dir.to_s},
40
+ "middleman #{command}",
41
+ streams)
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ attr_reader :streams, :fs, :sheller
48
+
49
+ end
50
+ end
@@ -0,0 +1,125 @@
1
+ require 'nokogiri'
2
+ require_relative '../css_link_checker'
3
+ require_relative 'redirection'
4
+
5
+ module Bookbinder
6
+ module Postprocessing
7
+ class LinkChecker
8
+ def initialize(fs, root_path, output_streams)
9
+ @fs = fs
10
+ @root_path = root_path
11
+ @output_streams = output_streams
12
+ @broken_link_count = 0
13
+
14
+ @convert_to_relative = %r{\A.*#{root_path.to_s}/public}
15
+ @default_link_exclusions = %r{\A(?:https?://|javascript:|mailto:)}
16
+ @excluded_pages = %r{\A/(?:404\.html|subnavs|javascripts|stylesheets|style_guide)}
17
+ end
18
+
19
+ def check!(link_exclusions = /(?!.*)/)
20
+ @output_streams[:out].puts "\nChecking for broken links..."
21
+ @redirects = Redirection.new(@fs, File.join(@root_path, 'redirects.rb'))
22
+ load_page_links
23
+
24
+ report_broken_links!(link_exclusions)
25
+ report_orphaned_pages!
26
+
27
+ if has_errors?
28
+ err "\nFound #{@broken_link_count} broken links!"
29
+ else
30
+ out "\nNo broken links!"
31
+ end
32
+ end
33
+
34
+ def has_errors?
35
+ @broken_link_count > 0
36
+ end
37
+
38
+ private
39
+
40
+ def report_broken_links!(link_exclusions)
41
+ @page_links.each do |page, links|
42
+ links.each do |link|
43
+ next if skip?(link, link_exclusions)
44
+
45
+ absolute_link, fragment = normalize_link(link, page)
46
+
47
+ if !page_exists?(absolute_link) && !file_exists?(absolute_link)
48
+ @broken_link_count += 1
49
+ err "#{page} => #{absolute_link}#{fragment ? "##{fragment}" : ''}"
50
+ end
51
+ end
52
+ end
53
+
54
+ broken_css_links = Dir.chdir(@root_path) { CssLinkChecker.new.broken_links_in_all_stylesheets }
55
+ broken_css_links.reject! { |link| link_exclusions.match(link) }
56
+
57
+ @broken_link_count += broken_css_links.size
58
+ broken_css_links.each do |link|
59
+ err link
60
+ end
61
+ end
62
+
63
+ def report_orphaned_pages!
64
+ linked_pages = @page_links.map do |page, links|
65
+ links.map do |link|
66
+ normalize_link(link, page)[0]
67
+ end
68
+ end.flatten.uniq
69
+
70
+ orphaned_pages = @page_links.keys.reject { |page| page == '/index.html' || linked_pages.include?(page) }
71
+ if orphaned_pages.size > 0
72
+ err "\nOrphaned pages"
73
+ orphaned_pages.each do |page|
74
+ err "No links to => #{page}"
75
+ end
76
+ end
77
+ end
78
+
79
+ def skip?(link_path, link_exclusions)
80
+ @default_link_exclusions.match(link_path) || link_path.match(link_exclusions)
81
+ end
82
+
83
+ def page_exists?(link)
84
+ @page_links.has_key?(link) || @redirects.redirected?(link)
85
+ end
86
+
87
+ def normalize_link(link, page)
88
+ return [page, link.sub(/\A#/, '')] if link[0] == '#'
89
+
90
+ absolute_link = link[0] == '/' ? link : File.expand_path(link, File.dirname(page))
91
+ absolute_link.split('#')
92
+ end
93
+
94
+ def file_exists?(link)
95
+ full_path = File.join(@root_path, 'public', link)
96
+ @fs.is_file?(full_path) || (@fs.is_dir?(full_path) && @fs.is_file?(File.join(full_path, 'index.html')))
97
+ end
98
+
99
+ def load_page_links
100
+ files = @fs.find_files_with_ext('html', File.join(@root_path, 'public'))
101
+
102
+ @page_links = files.each.with_object({}) do |file_path, links|
103
+ public_path = file_path.sub(@convert_to_relative, '')
104
+
105
+ if !@excluded_pages.match(public_path)
106
+ html = Nokogiri::HTML(@fs.read(file_path))
107
+
108
+ links[public_path] = [
109
+ html.css('a[href]').map { |link| link['href'] },
110
+ html.css('img').map { |image| image['src'] }
111
+ ].flatten
112
+ end
113
+ end
114
+ end
115
+
116
+ def out(str)
117
+ @output_streams[:out].puts(str)
118
+ end
119
+
120
+ def err(str)
121
+ @output_streams[:err].puts(str)
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,38 @@
1
+ module Bookbinder
2
+ module Postprocessing
3
+ class Redirection
4
+ def initialize(fs, file_path)
5
+ @redirect_regexes = {}
6
+ @redirect_strings = {}
7
+ load!(fs, file_path)
8
+ end
9
+
10
+ def redirected?(url)
11
+ @redirect_strings.has_key?(url) ||
12
+ @redirect_regexes.keys.detect {|regex| regex.match(url)}
13
+ end
14
+
15
+ private
16
+
17
+ def load!(fs, file_path)
18
+ if fs.is_file?(file_path)
19
+ contents = fs.read(file_path)
20
+ instance_eval contents
21
+ end
22
+ end
23
+
24
+ def r301(source, dest, options={})
25
+ return if options.has_key?(:if)
26
+
27
+ case source
28
+ when Regexp
29
+ @redirect_regexes[source] = dest
30
+ when String
31
+ @redirect_strings[source] = dest
32
+ end
33
+ end
34
+ alias r302 r301
35
+ alias rewrite r301
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,91 @@
1
+ require_relative '../values/subnav_template'
2
+ require_relative '../../../lib/bookbinder/subnav/navigation_entries_from_html_toc'
3
+
4
+ module Bookbinder
5
+ module Preprocessing
6
+ class DitaHTMLPreprocessor
7
+ DitaToHtmlLibraryFailure = Class.new(RuntimeError)
8
+
9
+ ACCEPTED_IMAGE_FORMATS = %w(png jpeg jpg svg gif bmp tif tiff eps)
10
+
11
+ def initialize(fs, subnav_gen_factory, dita_formatter, command_creator, sheller)
12
+ @fs = fs
13
+ @subnav_gen_factory = subnav_gen_factory
14
+ @dita_formatter = dita_formatter
15
+ @command_creator = command_creator
16
+ @sheller = sheller
17
+ end
18
+
19
+ def applicable_to?(section)
20
+ section.subnav_template.include?('dita_subnav') if section.subnav_template
21
+ end
22
+
23
+ def preprocess(sections, output_locations, options: {}, output_streams: nil, **_)
24
+ @output_locations = output_locations
25
+
26
+ sections.each do |section|
27
+ if section.path_to_preprocessor_attribute('ditamap_location')
28
+ convert_dita_files(section,
29
+ command_creator,
30
+ options[:dita_flags],
31
+ section_html_dir(section),
32
+ sheller,
33
+ output_streams)
34
+
35
+ subnav_generator.generate(section)
36
+ end
37
+
38
+ dita_formatter.format_html(section_html_dir(section), formatted_dir(section))
39
+ copy_images(section.path_to_repo_dir, formatted_dir(section))
40
+ fs.copy_contents(formatted_dir(section), source_for_site_gen_dir(section))
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ attr_reader :fs, :subnav_gen_factory, :dita_formatter, :command_creator, :sheller, :output_locations
47
+
48
+ def section_html_dir(section)
49
+ output_locations.html_from_preprocessing_dir.join(section.destination_directory)
50
+ end
51
+
52
+ def formatted_dir(section)
53
+ output_locations.formatted_dir.join(section.destination_directory)
54
+ end
55
+
56
+ def source_for_site_gen_dir(section)
57
+ output_locations.source_for_site_generator.join(section.destination_directory)
58
+ end
59
+
60
+ def convert_dita_files(section, command_creator, options, section_html_dir, sheller, output_streams)
61
+ command = command_creator.convert_to_html_command(
62
+ section,
63
+ dita_flags: options,
64
+ write_to: section_html_dir
65
+ )
66
+ status = sheller.run_command(command, output_streams.to_h)
67
+ unless status.success?
68
+ raise DitaToHtmlLibraryFailure.new 'The DITA-to-HTML conversion failed. ' +
69
+ 'Please check that you have specified the path to your DITA-OT library in the ENV, ' +
70
+ 'that your DITA-specific keys/values in config.yml are set, ' +
71
+ 'and that your DITA toolkit is correctly configured.'
72
+ end
73
+ end
74
+
75
+ def copy_images(src, dest)
76
+ image_paths = ACCEPTED_IMAGE_FORMATS.map do |format|
77
+ fs.find_files_with_ext(format, src)
78
+ end.flatten
79
+
80
+ image_paths.each do |image_path|
81
+ fs.copy_including_intermediate_dirs(image_path, src, dest)
82
+ end
83
+ end
84
+
85
+
86
+ def subnav_generator
87
+ @subnav_generator ||= subnav_gen_factory.produce(Subnav::NavigationEntriesFromHtmlToc.new(fs))
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,48 @@
1
+ module Bookbinder
2
+ module Preprocessing
3
+ class DitaPDFPreprocessor
4
+ DitaToPDFLibraryFailure = Class.new(RuntimeError)
5
+
6
+ def initialize(fs, command_creator, sheller)
7
+ @fs = fs
8
+ @command_creator = command_creator
9
+ @sheller = sheller
10
+ end
11
+
12
+ def applicable_to?(section)
13
+ !!section.pdf_output_filename
14
+ end
15
+
16
+ def preprocess(sections, output_locations, options: {}, output_streams: nil, **_)
17
+ sections.each do |section|
18
+ command = command_creator.convert_to_pdf_command(
19
+ section,
20
+ dita_flags: options[:dita_flags],
21
+ write_to: output_locations.pdf_from_preprocessing_dir
22
+ )
23
+ status = sheller.run_command(command, output_streams.to_h)
24
+
25
+ if status.success?
26
+ pdf_path = most_recent_pdf(output_locations.pdf_from_preprocessing_dir)
27
+ pdf_destination = output_locations.pdf_artifact_dir.join(section.pdf_output_filename)
28
+ fs.copy_and_rename(pdf_path, pdf_destination)
29
+ else
30
+ raise DitaToPDFLibraryFailure.new 'The DITA-to-PDF conversion failed. ' +
31
+ 'Please check that you have specified the path to your DITA-OT library in the ENV, ' +
32
+ 'that your DITA-specific keys/values in config.yml are set, ' +
33
+ 'and that your DITA toolkit is correctly configured.'
34
+ end
35
+ end
36
+ end
37
+
38
+ def most_recent_pdf(dir_path)
39
+ pdfs_by_modified_date = Dir.glob(dir_path + '**/*.pdf').sort_by{ |f| File.mtime(f) }
40
+ pdfs_by_modified_date.last
41
+ end
42
+
43
+ private
44
+
45
+ attr_reader :command_creator, :sheller, :fs
46
+ end
47
+ end
48
+ end