bookbindery 6.0.0 → 7.0.0
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.
- checksums.yaml +4 -4
- data/bookbinder.gemspec +2 -2
- data/lib/bookbinder/commands/bind.rb +2 -1
- data/lib/bookbinder/commands/bind/directory_preparer.rb +3 -12
- data/lib/bookbinder/commands/bind/layout_preparer.rb +23 -0
- data/lib/bookbinder/commands/collection.rb +22 -8
- data/lib/bookbinder/commands/watch.rb +2 -1
- data/lib/bookbinder/config/checkers/subnavs_checker.rb +49 -0
- data/lib/bookbinder/config/checkers/topics_checker.rb +37 -0
- data/lib/bookbinder/config/configuration.rb +14 -1
- data/lib/bookbinder/config/fetcher.rb +27 -8
- data/lib/bookbinder/config/section_config.rb +4 -0
- data/lib/bookbinder/config/subnav_config.rb +41 -0
- data/lib/bookbinder/config/topic_config.rb +29 -0
- data/lib/bookbinder/config/validator.rb +5 -1
- data/lib/bookbinder/dita_command_creator.rb +2 -2
- data/lib/bookbinder/dita_html_to_middleman_formatter.rb +2 -2
- data/lib/bookbinder/ingest/section_repository.rb +1 -2
- data/lib/bookbinder/local_filesystem_accessor.rb +14 -0
- data/lib/bookbinder/preprocessing/dita_preprocessor.rb +2 -2
- data/lib/bookbinder/preprocessing/link_to_site_gen_dir.rb +15 -3
- data/lib/bookbinder/server_director.rb +1 -1
- data/lib/bookbinder/subnav/json_from_config.rb +77 -0
- data/lib/bookbinder/subnav/json_from_html.rb +38 -0
- data/lib/bookbinder/subnav/json_props_creator.rb +35 -0
- data/lib/bookbinder/subnav/pdf_config_creator.rb +52 -0
- data/lib/bookbinder/subnav/subnav_generator.rb +19 -0
- data/lib/bookbinder/subnav/subnav_generator_factory.rb +35 -0
- data/lib/bookbinder/subnav/template_creator.rb +41 -0
- data/lib/bookbinder/values/output_locations.rb +4 -0
- data/lib/bookbinder/values/section.rb +2 -1
- data/lib/bookbinder/values/{subnav.rb → subnav_template.rb} +2 -2
- data/master_middleman/archive_drop_down_menu.rb +4 -0
- data/master_middleman/bookbinder_helpers.rb +4 -3
- data/master_middleman/compass_runner.rb +0 -0
- metadata +17 -5
- data/lib/bookbinder/subnav_formatter.rb +0 -37
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0fb5495aa9aaa1b4337177fd9659ff1770edb7d1
|
4
|
+
data.tar.gz: 6aaa6711faed7f97fb649b8f0a7d76b259fdbc6d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d9d3278fb5effbab9c2591a5700685a78af34d9095a28d16dd1eb95144188fa498607a920cbc30224347ae972ec7e870a6a88be060e7091e7961fd609762865b
|
7
|
+
data.tar.gz: ae8ebb4008aedf58c261ce94ab0569ea8bec4caacf367ce9c2b5f611523b5793cc9650b9f987579cb95b507fd64f20d5a5ed5b1d5b688e345c75a656ee6cd98b
|
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 = '
|
5
|
+
s.version = '7.0.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', 'Frank Kotsianas', 'Elena Sharma', 'Christa Hartsock']
|
@@ -14,7 +14,7 @@ Gem::Specification.new do |s|
|
|
14
14
|
s.bindir = 'install_bin'
|
15
15
|
s.executable = 'bookbinder'
|
16
16
|
|
17
|
-
s.required_ruby_version = '
|
17
|
+
s.required_ruby_version = '>= 2.0'
|
18
18
|
s.add_runtime_dependency 'fog-aws', ['~> 0.7.1']
|
19
19
|
s.add_runtime_dependency 'ansi', ['~> 1.4']
|
20
20
|
s.add_runtime_dependency 'unf', ['~> 0.1']
|
@@ -68,7 +68,8 @@ module Bookbinder
|
|
68
68
|
sections,
|
69
69
|
output_locations,
|
70
70
|
options: bind_options.options,
|
71
|
-
output_streams: bind_options.streams
|
71
|
+
output_streams: bind_options.streams,
|
72
|
+
config: bind_config
|
72
73
|
)
|
73
74
|
if file_system_accessor.file_exist?('redirects.rb')
|
74
75
|
file_system_accessor.copy('redirects.rb', output_locations.final_app_dir)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require_relative 'layout_preparer'
|
2
|
+
|
1
3
|
module Bookbinder
|
2
4
|
module Commands
|
3
5
|
module BindComponents
|
@@ -13,8 +15,7 @@ module Bookbinder
|
|
13
15
|
copy_directory_from_gem(gem_root, 'template_app', output_locations.final_app_dir)
|
14
16
|
copy_directory_from_gem(gem_root, 'master_middleman', output_locations.site_generator_home)
|
15
17
|
|
16
|
-
|
17
|
-
fs.copy_contents(layout_repo_path, output_locations.site_generator_home)
|
18
|
+
LayoutPreparer.new(fs).prepare(output_locations, cloner, config)
|
18
19
|
end
|
19
20
|
|
20
21
|
private
|
@@ -24,16 +25,6 @@ module Bookbinder
|
|
24
25
|
def copy_directory_from_gem(gem_root, dir, output_dir)
|
25
26
|
fs.copy_contents(File.join(gem_root, dir), output_dir)
|
26
27
|
end
|
27
|
-
|
28
|
-
def fetch_layout_repo(config, cloner)
|
29
|
-
if config.has_option?('layout_repo')
|
30
|
-
cloned_repo = cloner.call(source_repo_name: config.layout_repo,
|
31
|
-
destination_parent_dir: Dir.mktmpdir)
|
32
|
-
cloned_repo.path
|
33
|
-
else
|
34
|
-
File.absolute_path('master_middleman')
|
35
|
-
end
|
36
|
-
end
|
37
28
|
end
|
38
29
|
end
|
39
30
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Bookbinder
|
2
|
+
module Commands
|
3
|
+
module BindComponents
|
4
|
+
class LayoutPreparer
|
5
|
+
def initialize(fs)
|
6
|
+
@fs = fs
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :fs
|
10
|
+
|
11
|
+
def prepare(output_locations, cloner, config)
|
12
|
+
if config.has_option?('layout_repo')
|
13
|
+
cloned_repo = cloner.call(source_repo_name: config.layout_repo,
|
14
|
+
destination_parent_dir: Dir.mktmpdir)
|
15
|
+
|
16
|
+
fs.copy_contents(cloned_repo.path, output_locations.site_generator_home)
|
17
|
+
end
|
18
|
+
fs.copy_contents(File.absolute_path('master_middleman'), output_locations.site_generator_home)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -19,8 +19,9 @@ require_relative '../postprocessing/sitemap_writer'
|
|
19
19
|
require_relative '../preprocessing/dita_preprocessor'
|
20
20
|
require_relative '../preprocessing/link_to_site_gen_dir'
|
21
21
|
require_relative '../preprocessing/preprocessor'
|
22
|
+
require_relative '../subnav/subnav_generator_factory'
|
22
23
|
require_relative '../sheller'
|
23
|
-
require_relative '../
|
24
|
+
require_relative '../subnav/json_from_html'
|
24
25
|
require_relative '../values/output_locations'
|
25
26
|
|
26
27
|
module Bookbinder
|
@@ -87,7 +88,7 @@ module Bookbinder
|
|
87
88
|
def bind
|
88
89
|
@bind ||= Commands::Bind.new(
|
89
90
|
streams,
|
90
|
-
|
91
|
+
output_locations,
|
91
92
|
configuration_fetcher,
|
92
93
|
Config::ArchiveMenuConfiguration.new(loader: config_loader, config_filename: 'bookbinder.yml'),
|
93
94
|
local_filesystem_accessor,
|
@@ -95,12 +96,12 @@ module Bookbinder
|
|
95
96
|
Postprocessing::SitemapWriter.build(logger, final_app_directory, sitemap_port),
|
96
97
|
Preprocessing::Preprocessor.new(
|
97
98
|
Preprocessing::DitaPreprocessor.new(
|
98
|
-
DitaHtmlToMiddlemanFormatter.new(local_filesystem_accessor,
|
99
|
+
DitaHtmlToMiddlemanFormatter.new(local_filesystem_accessor, dita_json_generator, html_document_manipulator),
|
99
100
|
local_filesystem_accessor,
|
100
101
|
DitaCommandCreator.new(ENV['PATH_TO_DITA_OT_LIBRARY']),
|
101
102
|
sheller
|
102
103
|
),
|
103
|
-
Preprocessing::LinkToSiteGenDir.new(local_filesystem_accessor)
|
104
|
+
Preprocessing::LinkToSiteGenDir.new(local_filesystem_accessor, subnav_generator_factory)
|
104
105
|
),
|
105
106
|
Ingest::ClonerFactory.new(streams, local_filesystem_accessor, version_control_system),
|
106
107
|
Ingest::SectionRepository.new,
|
@@ -112,11 +113,11 @@ module Bookbinder
|
|
112
113
|
@watch ||= Commands::Watch.new(
|
113
114
|
streams,
|
114
115
|
middleman_runner: runner,
|
115
|
-
output_locations:
|
116
|
+
output_locations: output_locations,
|
116
117
|
config_fetcher: configuration_fetcher,
|
117
118
|
config_decorator: Config::ArchiveMenuConfiguration.new(loader: config_loader, config_filename: 'bookbinder.yml'),
|
118
119
|
file_system_accessor: local_filesystem_accessor,
|
119
|
-
preprocessor: Preprocessing::Preprocessor.new(Preprocessing::LinkToSiteGenDir.new(local_filesystem_accessor)),
|
120
|
+
preprocessor: Preprocessing::Preprocessor.new(Preprocessing::LinkToSiteGenDir.new(local_filesystem_accessor, subnav_generator_factory)),
|
120
121
|
cloner: local_file_system_cloner,
|
121
122
|
section_repository: Ingest::SectionRepository.new,
|
122
123
|
directory_preparer: directory_preparer
|
@@ -146,6 +147,7 @@ module Bookbinder
|
|
146
147
|
Config::RemoteYamlCredentialProvider.new(logger, version_control_system)
|
147
148
|
).tap do |fetcher|
|
148
149
|
fetcher.set_config_file_path './config.yml'
|
150
|
+
fetcher.set_config_dir_path './config/'
|
149
151
|
end
|
150
152
|
end
|
151
153
|
|
@@ -153,16 +155,28 @@ module Bookbinder
|
|
153
155
|
@config_loader ||= Config::YAMLLoader.new
|
154
156
|
end
|
155
157
|
|
158
|
+
def subnav_generator_factory
|
159
|
+
Subnav::SubnavGeneratorFactory.new(local_filesystem_accessor, output_locations)
|
160
|
+
end
|
161
|
+
|
162
|
+
def json_generator
|
163
|
+
Subnav::JsonFromConfig.new
|
164
|
+
end
|
165
|
+
|
156
166
|
def directory_preparer
|
157
167
|
Commands::BindComponents::DirectoryPreparer.new(local_filesystem_accessor)
|
158
168
|
end
|
159
169
|
|
170
|
+
def output_locations
|
171
|
+
OutputLocations.new(final_app_dir: final_app_directory, context_dir: File.absolute_path('.'))
|
172
|
+
end
|
173
|
+
|
160
174
|
def final_app_directory
|
161
175
|
@final_app_directory ||= File.absolute_path('final_app')
|
162
176
|
end
|
163
177
|
|
164
|
-
def
|
165
|
-
|
178
|
+
def dita_json_generator
|
179
|
+
Subnav::JsonFromHtml.new
|
166
180
|
end
|
167
181
|
|
168
182
|
def html_document_manipulator
|
@@ -51,7 +51,8 @@ module Bookbinder
|
|
51
51
|
preprocessor.preprocess(
|
52
52
|
sections,
|
53
53
|
output_locations,
|
54
|
-
output_streams: streams
|
54
|
+
output_streams: streams,
|
55
|
+
config: watch_config
|
55
56
|
)
|
56
57
|
if file_system_accessor.file_exist?('redirects.rb')
|
57
58
|
file_system_accessor.copy('redirects.rb', output_locations.final_app_dir)
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Bookbinder
|
2
|
+
module Config
|
3
|
+
module Checkers
|
4
|
+
class SubnavsChecker
|
5
|
+
MissingRequiredKeyError = Class.new(RuntimeError)
|
6
|
+
MissingSubnavsKeyError = Class.new(RuntimeError)
|
7
|
+
MissingSubnavNameError = Class.new(RuntimeError)
|
8
|
+
|
9
|
+
def check(config)
|
10
|
+
@config = config
|
11
|
+
|
12
|
+
if section_subnav_names.count > 0
|
13
|
+
if config.subnavs.empty?
|
14
|
+
MissingSubnavsKeyError.new("You must specify at least one subnav under the subnavs key in config.yml")
|
15
|
+
elsif missing_subnavs.count != 0
|
16
|
+
MissingSubnavNameError.new("Your config.yml is missing required subnav names under the subnavs key. Required subnav names are #{missing_subnavs.join(", ")}.")
|
17
|
+
elsif invalid_subnavs.any?
|
18
|
+
MissingRequiredKeyError.new("Your config.yml is missing required key(s) for subnavs #{invalid_subnav_names}. Required keys are #{required_subnav_keys.join(", ")}.")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_reader :config
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def invalid_subnavs
|
28
|
+
config.subnavs.map {|subnav_config| subnav_config unless subnav_config.valid? }
|
29
|
+
end
|
30
|
+
|
31
|
+
def invalid_subnav_names
|
32
|
+
invalid_subnavs.map(&:name).join(", ")
|
33
|
+
end
|
34
|
+
|
35
|
+
def missing_subnavs
|
36
|
+
section_subnav_names - config.subnavs.map(&:name)
|
37
|
+
end
|
38
|
+
|
39
|
+
def required_subnav_keys
|
40
|
+
Bookbinder::Config::SubnavConfig::CONFIG_REQUIRED_KEYS
|
41
|
+
end
|
42
|
+
|
43
|
+
def section_subnav_names
|
44
|
+
config.sections.map(&:subnav_name).compact.uniq
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Bookbinder
|
2
|
+
module Config
|
3
|
+
module Checkers
|
4
|
+
class TopicsChecker
|
5
|
+
MissingRequiredKeyError = Class.new(RuntimeError)
|
6
|
+
|
7
|
+
def check(config)
|
8
|
+
@config = config
|
9
|
+
|
10
|
+
if invalid_subnavs.any?
|
11
|
+
MissingRequiredKeyError.new("Your config.yml is missing required key(s) for subnav(s) #{invalid_subnav_names}. Required keys are #{required_topic_keys.join(", ")}.")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :config
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def invalid_subnavs
|
20
|
+
config.subnavs.select { |subnav_config| invalid_topics(subnav_config.topics).any? }
|
21
|
+
end
|
22
|
+
|
23
|
+
def invalid_topics(topics)
|
24
|
+
topics.map {|topic| topic unless topic.valid? }
|
25
|
+
end
|
26
|
+
|
27
|
+
def invalid_subnav_names
|
28
|
+
invalid_subnavs.map(&:name).join(', ')
|
29
|
+
end
|
30
|
+
|
31
|
+
def required_topic_keys
|
32
|
+
Bookbinder::Config::TopicConfig::CONFIG_REQUIRED_KEYS
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require_relative '../ingest/destination_directory'
|
2
2
|
require_relative '../ingest/repo_identifier'
|
3
3
|
require_relative 'section_config'
|
4
|
+
require_relative 'subnav_config'
|
4
5
|
|
5
6
|
module Bookbinder
|
6
7
|
module Config
|
@@ -65,10 +66,11 @@ module Bookbinder
|
|
65
66
|
|
66
67
|
def initialize(config)
|
67
68
|
@config = config
|
69
|
+
@subnavs = assemble_subnavs || []
|
68
70
|
end
|
69
71
|
|
70
72
|
CONFIG_REQUIRED_KEYS = %w(book_repo public_host)
|
71
|
-
CONFIG_OPTIONAL_KEYS = %w(archive_menu book_repo_url cred_repo cred_repo_url layout_repo layout_repo_url sections)
|
73
|
+
CONFIG_OPTIONAL_KEYS = %w(archive_menu book_repo_url cred_repo cred_repo_url layout_repo layout_repo_url sections subnav_exclusions)
|
72
74
|
|
73
75
|
CONFIG_REQUIRED_KEYS.each do |method_name|
|
74
76
|
define_method(method_name) do
|
@@ -108,8 +110,19 @@ module Bookbinder
|
|
108
110
|
|
109
111
|
alias_method :eql?, :==
|
110
112
|
|
113
|
+
attr_reader :subnavs
|
114
|
+
|
111
115
|
private
|
112
116
|
|
117
|
+
def assemble_subnavs
|
118
|
+
if config[:subnavs]
|
119
|
+
config[:subnavs].map do |subnav|
|
120
|
+
subnav.merge!({'subnav_exclusions' => subnav_exclusions})
|
121
|
+
Config::SubnavConfig.new(subnav)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
113
126
|
attr_reader :config
|
114
127
|
end
|
115
128
|
end
|
@@ -13,7 +13,10 @@ module Bookbinder
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def fetch_config
|
16
|
-
@
|
16
|
+
@base_config ||= read_config_file
|
17
|
+
@optional_configs ||= read_optional_configs
|
18
|
+
|
19
|
+
@config ||= validate(@base_config, @optional_configs)
|
17
20
|
end
|
18
21
|
|
19
22
|
def fetch_credentials(environment = 'null-environment')
|
@@ -29,13 +32,17 @@ module Bookbinder
|
|
29
32
|
}
|
30
33
|
end
|
31
34
|
|
32
|
-
def
|
33
|
-
@
|
35
|
+
def set_config_dir_path(config_dir_path)
|
36
|
+
@config_dir_path = File.expand_path(config_dir_path)
|
37
|
+
end
|
38
|
+
|
39
|
+
def set_config_file_path(config_file_path)
|
40
|
+
@config_file_path = File.expand_path(config_file_path)
|
34
41
|
end
|
35
42
|
|
36
43
|
private
|
37
44
|
|
38
|
-
attr_reader(:loader, :configuration_validator, :config, :config_file_path,
|
45
|
+
attr_reader(:loader, :configuration_validator, :config, :config_file_path, :config_dir_path,
|
39
46
|
:credentials_provider)
|
40
47
|
|
41
48
|
def read_config_file
|
@@ -44,17 +51,29 @@ module Bookbinder
|
|
44
51
|
rescue FileNotFoundError => e
|
45
52
|
raise "The configuration file specified does not exist. Please create a config #{e} file at #{config_file_path} and try again."
|
46
53
|
rescue InvalidSyntaxError => e
|
47
|
-
raise
|
54
|
+
raise syntax_error(e)
|
55
|
+
end
|
56
|
+
|
57
|
+
def read_optional_configs
|
58
|
+
Dir["#{config_dir_path}/*.yml"].map do |config_file|
|
59
|
+
loader.load(File.expand_path(config_file)) || {}
|
60
|
+
end.reduce({}, :merge)
|
61
|
+
rescue InvalidSyntaxError => e
|
62
|
+
raise syntax_error(e)
|
48
63
|
end
|
49
64
|
|
50
|
-
def validate(
|
51
|
-
raise 'Your config.yml appears to be empty. Please check and try again.' unless
|
65
|
+
def validate(base_hash, optional_hash)
|
66
|
+
raise 'Your config.yml appears to be empty. Please check and try again.' unless base_hash
|
52
67
|
|
53
|
-
Configuration.parse(
|
68
|
+
Configuration.parse(base_hash.merge(optional_hash)).tap do |config|
|
54
69
|
errors = configuration_validator.exceptions(config)
|
55
70
|
raise errors.first if errors.any?
|
56
71
|
end
|
57
72
|
end
|
73
|
+
|
74
|
+
def syntax_error(e)
|
75
|
+
"There is a syntax error in your config file: \n #{e}"
|
76
|
+
end
|
58
77
|
end
|
59
78
|
end
|
60
79
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative '../config/topic_config'
|
2
|
+
|
3
|
+
module Bookbinder
|
4
|
+
module Config
|
5
|
+
class SubnavConfig
|
6
|
+
def initialize(config)
|
7
|
+
@config = config
|
8
|
+
@topics = assemble_topics || []
|
9
|
+
end
|
10
|
+
|
11
|
+
def name
|
12
|
+
config['name']
|
13
|
+
end
|
14
|
+
|
15
|
+
def pdf_config
|
16
|
+
config['pdf_config']
|
17
|
+
end
|
18
|
+
|
19
|
+
def subnav_exclusions
|
20
|
+
config['subnav_exclusions'] || []
|
21
|
+
end
|
22
|
+
|
23
|
+
def valid?
|
24
|
+
(CONFIG_REQUIRED_KEYS - config.keys).empty?
|
25
|
+
end
|
26
|
+
|
27
|
+
CONFIG_REQUIRED_KEYS = %w(name topics)
|
28
|
+
|
29
|
+
attr_reader :topics
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
attr_reader :config
|
34
|
+
|
35
|
+
def assemble_topics
|
36
|
+
config['topics'].map{|topic| Config::TopicConfig.new(topic)} if config['topics']
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Bookbinder
|
2
|
+
module Config
|
3
|
+
class TopicConfig
|
4
|
+
def initialize(config)
|
5
|
+
@config = config
|
6
|
+
end
|
7
|
+
|
8
|
+
def title
|
9
|
+
config['title']
|
10
|
+
end
|
11
|
+
|
12
|
+
def toc_path
|
13
|
+
Pathname(config['toc_path'])
|
14
|
+
end
|
15
|
+
|
16
|
+
def toc_nav_name
|
17
|
+
config['toc_nav_name'] || title
|
18
|
+
end
|
19
|
+
|
20
|
+
def valid?
|
21
|
+
(CONFIG_REQUIRED_KEYS - config.keys).empty?
|
22
|
+
end
|
23
|
+
|
24
|
+
CONFIG_REQUIRED_KEYS = %w(title toc_path)
|
25
|
+
|
26
|
+
attr_reader :config
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -3,6 +3,8 @@ require_relative 'checkers/archive_menu_checker'
|
|
3
3
|
require_relative 'checkers/required_keys_checker'
|
4
4
|
require_relative 'checkers/repository_name_presence_checker'
|
5
5
|
require_relative 'checkers/dita_section_checker'
|
6
|
+
require_relative 'checkers/subnavs_checker'
|
7
|
+
require_relative 'checkers/topics_checker'
|
6
8
|
|
7
9
|
module Bookbinder
|
8
10
|
module Config
|
@@ -17,7 +19,9 @@ module Bookbinder
|
|
17
19
|
Checkers::DuplicateSectionNameChecker.new,
|
18
20
|
Checkers::RepositoryNamePresenceChecker.new,
|
19
21
|
Checkers::DitaSectionChecker.new,
|
20
|
-
Checkers::ArchiveMenuChecker.new(@file_system_accessor)
|
22
|
+
Checkers::ArchiveMenuChecker.new(@file_system_accessor),
|
23
|
+
Checkers::SubnavsChecker.new,
|
24
|
+
Checkers::TopicsChecker.new
|
21
25
|
].map do |checker|
|
22
26
|
checker.check(config)
|
23
27
|
end
|
@@ -24,13 +24,13 @@ module Bookbinder
|
|
24
24
|
write_to: write_to,
|
25
25
|
dita_flags: dita_flags,
|
26
26
|
ditamap_path: dita_section.path_to_preprocessor_attribute('ditamap_location'),
|
27
|
-
ditaval_path: dita_section.path_to_preprocessor_attribute('ditaval_location')
|
27
|
+
ditaval_path: dita_section.path_to_preprocessor_attribute('ditaval_location')
|
28
28
|
)
|
29
29
|
end
|
30
30
|
|
31
31
|
private
|
32
32
|
|
33
|
-
def unduplicated_flags(write_to: nil, ditamap_path: nil, ditaval_path: nil, dita_flags:
|
33
|
+
def unduplicated_flags(write_to: nil, ditamap_path: nil, ditaval_path: nil, dita_flags: nil)
|
34
34
|
arg_flags = {
|
35
35
|
'output.dir' => write_to,
|
36
36
|
'args.input' => ditamap_path,
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require_relative 'values/
|
1
|
+
require_relative 'values/subnav_template'
|
2
2
|
|
3
3
|
module Bookbinder
|
4
4
|
|
@@ -40,7 +40,7 @@ module Bookbinder
|
|
40
40
|
selector: 'div.nav-content',
|
41
41
|
attribute: 'data-props-location',
|
42
42
|
value: json_props_location)
|
43
|
-
|
43
|
+
SubnavTemplate.new(formatted_json_links, nav_text)
|
44
44
|
end
|
45
45
|
|
46
46
|
private
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'tmpdir'
|
2
|
-
require_relative '../deprecated_logger'
|
3
1
|
require_relative '../values/section'
|
4
2
|
|
5
3
|
module Bookbinder
|
@@ -21,6 +19,7 @@ module Bookbinder
|
|
21
19
|
working_copy.full_name,
|
22
20
|
section_config.desired_directory_name,
|
23
21
|
section_config.subnav_template,
|
22
|
+
section_config.subnav_name,
|
24
23
|
section_config.preprocessor_config
|
25
24
|
)
|
26
25
|
end
|
@@ -20,6 +20,11 @@ module Bookbinder
|
|
20
20
|
to
|
21
21
|
end
|
22
22
|
|
23
|
+
def overwrite(to: nil, text: nil)
|
24
|
+
File.delete(to) if file_exist?(to)
|
25
|
+
write(to: to, text: text)
|
26
|
+
end
|
27
|
+
|
23
28
|
def read(path)
|
24
29
|
File.read(path)
|
25
30
|
end
|
@@ -80,5 +85,14 @@ module Bookbinder
|
|
80
85
|
reject {|p| p.to_s.match %r{/\.}}.
|
81
86
|
reject(&:directory?)
|
82
87
|
end
|
88
|
+
|
89
|
+
def find_files_extension_agnostically(pattern, directory='.')
|
90
|
+
extensionless_pattern = pattern.to_s.split('.').first
|
91
|
+
|
92
|
+
`find -L #{directory} -path '*/#{extensionless_pattern}.*'`.
|
93
|
+
lines.
|
94
|
+
map(&:chomp).
|
95
|
+
map(&Pathname.method(:new))
|
96
|
+
end
|
83
97
|
end
|
84
98
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require_relative '../values/
|
1
|
+
require_relative '../values/subnav_template'
|
2
2
|
|
3
3
|
module Bookbinder
|
4
4
|
module Preprocessing
|
@@ -18,7 +18,7 @@ module Bookbinder
|
|
18
18
|
section.subnav_template.include?('dita_subnav') if section.subnav_template
|
19
19
|
end
|
20
20
|
|
21
|
-
def preprocess(dita_sections, output_locations, options: [], output_streams: nil)
|
21
|
+
def preprocess(dita_sections, output_locations, options: [], output_streams: nil, **_)
|
22
22
|
dita_options = dita_flags(options)
|
23
23
|
dita_sections.each do |dita_section|
|
24
24
|
if dita_section.path_to_preprocessor_attribute('ditamap_location')
|
@@ -1,26 +1,38 @@
|
|
1
|
+
require_relative '../subnav/subnav_generator'
|
2
|
+
require_relative '../subnav/json_from_config'
|
3
|
+
|
1
4
|
module Bookbinder
|
2
5
|
module Preprocessing
|
3
6
|
class LinkToSiteGenDir
|
4
|
-
def initialize(filesystem)
|
7
|
+
def initialize(filesystem, subnav_generator_factory)
|
5
8
|
@filesystem = filesystem
|
9
|
+
@subnav_generator_factory = subnav_generator_factory
|
6
10
|
end
|
7
11
|
|
8
12
|
def applicable_to?(section)
|
9
13
|
filesystem.file_exist?(section.path_to_repository)
|
10
14
|
end
|
11
15
|
|
12
|
-
def preprocess(sections, output_locations,
|
16
|
+
def preprocess(sections, output_locations, config: nil, **_)
|
13
17
|
sections.each do |section|
|
14
18
|
filesystem.link_creating_intermediate_dirs(
|
15
19
|
section.path_to_repository,
|
16
20
|
output_locations.source_for_site_generator.join(section.destination_directory)
|
17
21
|
)
|
18
22
|
end
|
23
|
+
|
24
|
+
config.subnavs.each do |subnav|
|
25
|
+
subnav_generator.generate(subnav)
|
26
|
+
end
|
19
27
|
end
|
20
28
|
|
21
29
|
private
|
22
30
|
|
23
|
-
|
31
|
+
def subnav_generator
|
32
|
+
@subnav_generator ||= subnav_generator_factory.produce(Subnav::JsonFromConfig.new(filesystem))
|
33
|
+
end
|
34
|
+
|
35
|
+
attr_reader :filesystem, :subnav_generator_factory
|
24
36
|
end
|
25
37
|
end
|
26
38
|
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'redcarpet'
|
4
|
+
|
5
|
+
module Bookbinder
|
6
|
+
module Subnav
|
7
|
+
class JsonFromConfig
|
8
|
+
def initialize(fs)
|
9
|
+
@fs = fs
|
10
|
+
@renderer = Redcarpet::Markdown.new(Redcarpet::Render::HTML.new)
|
11
|
+
end
|
12
|
+
|
13
|
+
def get_links(subnav_config, source_for_site_gen)
|
14
|
+
@source_for_site_gen = source_for_site_gen
|
15
|
+
@config = subnav_config
|
16
|
+
|
17
|
+
{ links: get_links_and_headers }.to_json
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :fs, :source_for_site_gen, :renderer, :config
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def get_links_and_headers
|
25
|
+
menu_items = []
|
26
|
+
|
27
|
+
config.topics.map do |topic|
|
28
|
+
menu_items << { text: topic.title, title: true }
|
29
|
+
menu_items << { url: "/#{topic.toc_path}.html", text: topic.toc_nav_name }
|
30
|
+
|
31
|
+
links_from_toc_page = parse_toc_file(topic)
|
32
|
+
links_from_toc_page.each {|link| menu_items << link}
|
33
|
+
end
|
34
|
+
|
35
|
+
menu_items
|
36
|
+
end
|
37
|
+
|
38
|
+
def parse_toc_file(topic)
|
39
|
+
toc_files = fs.find_files_extension_agnostically(topic.toc_path, source_for_site_gen)
|
40
|
+
toc_md = fs.read(toc_files.first)
|
41
|
+
|
42
|
+
toc_html = get_html(toc_md)
|
43
|
+
|
44
|
+
gather_urls_and_texts(toc_html.css('html'), topic)
|
45
|
+
end
|
46
|
+
|
47
|
+
def get_html(md)
|
48
|
+
Nokogiri::HTML(renderer.render(md))
|
49
|
+
end
|
50
|
+
|
51
|
+
def gather_urls_and_texts(base_node, topic)
|
52
|
+
nav_items(base_node).map do |element|
|
53
|
+
if element.name == 'h2' && !frontmatter_header?(element)
|
54
|
+
{text: element.inner_html}
|
55
|
+
else
|
56
|
+
list_elements = element.css('li > a', 'li > p > a')
|
57
|
+
list_elements.map do |li|
|
58
|
+
{ url: "/#{topic.toc_path.dirname.join(li['href'])}", text: li.inner_text }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end.flatten
|
62
|
+
end
|
63
|
+
|
64
|
+
def nav_items(base_node)
|
65
|
+
base_node.css('h2, ul') - base_node.css(*exclusions)
|
66
|
+
end
|
67
|
+
|
68
|
+
def exclusions
|
69
|
+
@exclusions ||= config.subnav_exclusions << '.nav-exclude'
|
70
|
+
end
|
71
|
+
|
72
|
+
def frontmatter_header?(element)
|
73
|
+
element.inner_html.include?('title: ')
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'active_support/all'
|
3
|
+
|
4
|
+
module Bookbinder
|
5
|
+
module Subnav
|
6
|
+
class JsonFromHtml
|
7
|
+
def get_links_as_json(raw_subnav_text, base_dirname)
|
8
|
+
doc = Nokogiri::XML(raw_subnav_text)
|
9
|
+
|
10
|
+
all_anchors = doc.css('a')
|
11
|
+
all_anchors.each do |anchor|
|
12
|
+
anchor['href'] = "/#{base_dirname}/#{anchor['href']}"
|
13
|
+
end
|
14
|
+
|
15
|
+
{
|
16
|
+
links: gather_urls_and_texts(doc.css('body > ul'))
|
17
|
+
}.to_json
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def gather_urls_and_texts(base_node)
|
23
|
+
top_level_li = base_node.css("> li")
|
24
|
+
top_level_li.map do |li|
|
25
|
+
anchor = li.css('a')[0]
|
26
|
+
href = anchor['href']
|
27
|
+
text = anchor.inner_text
|
28
|
+
ul = li.css('> ul')
|
29
|
+
if ul.size > 0
|
30
|
+
{url: href, text: text, nestedLinks: gather_urls_and_texts(ul)}
|
31
|
+
else
|
32
|
+
{url: href, text: text}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Bookbinder
|
2
|
+
module Subnav
|
3
|
+
class JsonPropsCreator
|
4
|
+
def initialize(fs, output_locations, json_generator)
|
5
|
+
@fs = fs
|
6
|
+
@output_locations = output_locations
|
7
|
+
@json_generator = json_generator
|
8
|
+
end
|
9
|
+
|
10
|
+
def create(subnav_config)
|
11
|
+
json_links = json_generator.get_links(subnav_config, output_locations.source_for_site_generator)
|
12
|
+
|
13
|
+
fs.write(text: json_links, to: props_path(subnav_config.name))
|
14
|
+
|
15
|
+
filename(subnav_config.name)
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_reader :fs, :output_locations, :json_generator
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def filename(name)
|
23
|
+
"#{name}-props.json"
|
24
|
+
end
|
25
|
+
|
26
|
+
def subnavs_path
|
27
|
+
output_locations.subnavs_for_layout_dir
|
28
|
+
end
|
29
|
+
|
30
|
+
def props_path(name)
|
31
|
+
subnavs_path.join(filename(name))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require "json"
|
3
|
+
|
4
|
+
module Bookbinder
|
5
|
+
module Subnav
|
6
|
+
class PdfConfigCreator
|
7
|
+
def initialize(fs, output_locations)
|
8
|
+
@fs = fs
|
9
|
+
@output_locations = output_locations
|
10
|
+
end
|
11
|
+
|
12
|
+
def create(props_filename, subnav_config)
|
13
|
+
json = JSON.parse(fs.read(props_location(props_filename)))
|
14
|
+
@links = format_links(json['links'])
|
15
|
+
|
16
|
+
fs.overwrite(to: output_locations.pdf_config_dir.join(subnav_config.pdf_config),
|
17
|
+
text: config_content)
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :fs, :output_locations
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def props_location(filename)
|
25
|
+
output_locations.subnavs_for_layout_dir.join(filename)
|
26
|
+
end
|
27
|
+
|
28
|
+
def format_links(links)
|
29
|
+
links.map{|item| item['url'] }.compact.map{|link| link.sub(/^\//, '')}
|
30
|
+
end
|
31
|
+
|
32
|
+
def config_content
|
33
|
+
config_keys.inject({}) do |hash, key|
|
34
|
+
hash[key] = content_for(key)
|
35
|
+
hash
|
36
|
+
end.to_yaml
|
37
|
+
end
|
38
|
+
|
39
|
+
def config_keys
|
40
|
+
%w{copyright_notice header executable pages}
|
41
|
+
end
|
42
|
+
|
43
|
+
def content_for(key)
|
44
|
+
key == 'pages' ? @links : default_content
|
45
|
+
end
|
46
|
+
|
47
|
+
def default_content
|
48
|
+
'REPLACE ME'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Bookbinder
|
2
|
+
module Subnav
|
3
|
+
class SubnavGenerator
|
4
|
+
def initialize(json_props_creator, template_creator, pdf_config_creator)
|
5
|
+
@json_props_creator = json_props_creator
|
6
|
+
@template_creator = template_creator
|
7
|
+
@pdf_config_creator = pdf_config_creator
|
8
|
+
end
|
9
|
+
|
10
|
+
def generate(subnav_config)
|
11
|
+
filename = json_props_creator.create(subnav_config)
|
12
|
+
template_creator.create(filename, subnav_config)
|
13
|
+
pdf_config_creator.create(filename, subnav_config) if subnav_config.pdf_config
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :json_props_creator, :template_creator, :pdf_config_creator
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative 'json_props_creator'
|
2
|
+
require_relative 'template_creator'
|
3
|
+
require_relative 'pdf_config_creator'
|
4
|
+
require_relative '../html_document_manipulator'
|
5
|
+
|
6
|
+
module Bookbinder
|
7
|
+
module Subnav
|
8
|
+
class SubnavGeneratorFactory
|
9
|
+
def initialize(fs, output_locations)
|
10
|
+
@fs = fs
|
11
|
+
@output_locations = output_locations
|
12
|
+
end
|
13
|
+
|
14
|
+
def produce(json_generator)
|
15
|
+
SubnavGenerator.new(json_props_creator(json_generator), template_creator, pdf_config_creator)
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_reader :fs, :output_locations
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def json_props_creator(json_generator)
|
23
|
+
@json_props_creator ||= JsonPropsCreator.new(fs, output_locations, json_generator)
|
24
|
+
end
|
25
|
+
|
26
|
+
def template_creator
|
27
|
+
@template_creator ||= TemplateCreator.new(fs, output_locations, HtmlDocumentManipulator.new)
|
28
|
+
end
|
29
|
+
|
30
|
+
def pdf_config_creator
|
31
|
+
@pdf_config_creator ||= PdfConfigCreator.new(fs, output_locations)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Bookbinder
|
2
|
+
module Subnav
|
3
|
+
class TemplateCreator
|
4
|
+
def initialize(fs, output_locations, html_doc_manipulator)
|
5
|
+
@fs = fs
|
6
|
+
@output_locations = output_locations
|
7
|
+
@html_doc_manipulator = html_doc_manipulator
|
8
|
+
end
|
9
|
+
|
10
|
+
def create(props_filename, subnav_config)
|
11
|
+
template_content = fs.read(template_path)
|
12
|
+
nav_content = html_doc_manipulator.set_attribute(document: template_content,
|
13
|
+
selector: 'div.nav-content',
|
14
|
+
attribute: 'data-props-location',
|
15
|
+
value: props_filename)
|
16
|
+
|
17
|
+
fs.write(text: nav_content, to: subnav_destination(subnav_config.name))
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :fs, :output_locations, :html_doc_manipulator
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def subnavs_path
|
25
|
+
output_locations.subnavs_for_layout_dir
|
26
|
+
end
|
27
|
+
|
28
|
+
def filename(name)
|
29
|
+
"#{name}.erb"
|
30
|
+
end
|
31
|
+
|
32
|
+
def template_path
|
33
|
+
subnavs_path.join('subnav_template.erb')
|
34
|
+
end
|
35
|
+
|
36
|
+
def subnav_destination(name)
|
37
|
+
subnavs_path.join(filename(name))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -6,6 +6,7 @@ module Bookbinder
|
|
6
6
|
:full_name,
|
7
7
|
:desired_directory_name,
|
8
8
|
:subnav_templ,
|
9
|
+
:subnav_name,
|
9
10
|
:preprocessor_config) do
|
10
11
|
def path_to_repository
|
11
12
|
Pathname(self[:path_to_repository].to_s)
|
@@ -21,7 +22,7 @@ module Bookbinder
|
|
21
22
|
|
22
23
|
def subnav
|
23
24
|
namespace = destination_directory.to_s.gsub('/', '_')
|
24
|
-
template = subnav_template || 'default'
|
25
|
+
template = subnav_template || subnav_name || 'default'
|
25
26
|
{namespace => template}
|
26
27
|
end
|
27
28
|
|
@@ -48,9 +48,10 @@ module Bookbinder
|
|
48
48
|
config[:archive_menu],
|
49
49
|
current_path: current_page.path
|
50
50
|
)
|
51
|
-
|
52
|
-
|
53
|
-
|
51
|
+
unless menu.empty?
|
52
|
+
partial 'archive_menus/default', locals: { menu_title: menu.title,
|
53
|
+
dropdown_links: menu.dropdown_links }
|
54
|
+
end
|
54
55
|
end
|
55
56
|
|
56
57
|
def modified_date(format="%B %-d, %Y")
|
File without changes
|
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:
|
4
|
+
version: 7.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Grafton
|
@@ -17,7 +17,7 @@ authors:
|
|
17
17
|
autorequire:
|
18
18
|
bindir: install_bin
|
19
19
|
cert_chain: []
|
20
|
-
date: 2015-
|
20
|
+
date: 2015-10-10 00:00:00.000000000 Z
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
23
23
|
name: fog-aws
|
@@ -301,6 +301,7 @@ files:
|
|
301
301
|
- lib/bookbinder/command_validator.rb
|
302
302
|
- lib/bookbinder/commands/bind/bind_options.rb
|
303
303
|
- lib/bookbinder/commands/bind/directory_preparer.rb
|
304
|
+
- lib/bookbinder/commands/bind/layout_preparer.rb
|
304
305
|
- lib/bookbinder/commands/bind.rb
|
305
306
|
- lib/bookbinder/commands/build_and_push_tarball.rb
|
306
307
|
- lib/bookbinder/commands/chain.rb
|
@@ -322,10 +323,14 @@ files:
|
|
322
323
|
- lib/bookbinder/config/checkers/duplicate_section_name_checker.rb
|
323
324
|
- lib/bookbinder/config/checkers/repository_name_presence_checker.rb
|
324
325
|
- lib/bookbinder/config/checkers/required_keys_checker.rb
|
326
|
+
- lib/bookbinder/config/checkers/subnavs_checker.rb
|
327
|
+
- lib/bookbinder/config/checkers/topics_checker.rb
|
325
328
|
- lib/bookbinder/config/configuration.rb
|
326
329
|
- lib/bookbinder/config/fetcher.rb
|
327
330
|
- lib/bookbinder/config/remote_yaml_credential_provider.rb
|
328
331
|
- lib/bookbinder/config/section_config.rb
|
332
|
+
- lib/bookbinder/config/subnav_config.rb
|
333
|
+
- lib/bookbinder/config/topic_config.rb
|
329
334
|
- lib/bookbinder/config/validator.rb
|
330
335
|
- lib/bookbinder/config/yaml_loader.rb
|
331
336
|
- lib/bookbinder/css_link_checker.rb
|
@@ -370,11 +375,17 @@ files:
|
|
370
375
|
- lib/bookbinder/spider.rb
|
371
376
|
- lib/bookbinder/stabilimentum.rb
|
372
377
|
- lib/bookbinder/streams/colorized_stream.rb
|
373
|
-
- lib/bookbinder/
|
378
|
+
- lib/bookbinder/subnav/json_from_config.rb
|
379
|
+
- lib/bookbinder/subnav/json_from_html.rb
|
380
|
+
- lib/bookbinder/subnav/json_props_creator.rb
|
381
|
+
- lib/bookbinder/subnav/pdf_config_creator.rb
|
382
|
+
- lib/bookbinder/subnav/subnav_generator.rb
|
383
|
+
- lib/bookbinder/subnav/subnav_generator_factory.rb
|
384
|
+
- lib/bookbinder/subnav/template_creator.rb
|
374
385
|
- lib/bookbinder/terminal.rb
|
375
386
|
- lib/bookbinder/values/output_locations.rb
|
376
387
|
- lib/bookbinder/values/section.rb
|
377
|
-
- lib/bookbinder/values/
|
388
|
+
- lib/bookbinder/values/subnav_template.rb
|
378
389
|
- lib/bookbinder/values/user_message.rb
|
379
390
|
- template_app/app.rb
|
380
391
|
- template_app/config.ru
|
@@ -385,6 +396,7 @@ files:
|
|
385
396
|
- template_app/rack_app.rb
|
386
397
|
- master_middleman/archive_drop_down_menu.rb
|
387
398
|
- master_middleman/bookbinder_helpers.rb
|
399
|
+
- master_middleman/compass_runner.rb
|
388
400
|
- master_middleman/config.rb
|
389
401
|
- master_middleman/quicklinks_renderer.rb
|
390
402
|
- master_middleman/subdirectory_aware_assets.rb
|
@@ -400,7 +412,7 @@ require_paths:
|
|
400
412
|
- lib
|
401
413
|
required_ruby_version: !ruby/object:Gem::Requirement
|
402
414
|
requirements:
|
403
|
-
- -
|
415
|
+
- - '>='
|
404
416
|
- !ruby/object:Gem::Version
|
405
417
|
version: '2.0'
|
406
418
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
@@ -1,37 +0,0 @@
|
|
1
|
-
require 'nokogiri'
|
2
|
-
require 'active_support/all'
|
3
|
-
|
4
|
-
module Bookbinder
|
5
|
-
class SubnavFormatter
|
6
|
-
|
7
|
-
def get_links_as_json(raw_subnav_text, base_dirname)
|
8
|
-
doc = Nokogiri::XML(raw_subnav_text)
|
9
|
-
|
10
|
-
all_anchors = doc.css('a')
|
11
|
-
all_anchors.each do |anchor|
|
12
|
-
anchor['href'] = "/#{base_dirname}/#{anchor['href']}"
|
13
|
-
end
|
14
|
-
|
15
|
-
{
|
16
|
-
links: gather_urls_and_texts(doc.css('body > ul'))
|
17
|
-
}.to_json
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
def gather_urls_and_texts(base_node)
|
23
|
-
top_level_li = base_node.css("> li")
|
24
|
-
top_level_li.map do |li|
|
25
|
-
anchor = li.css('a')[0]
|
26
|
-
href = anchor['href']
|
27
|
-
text = anchor.inner_text
|
28
|
-
ul = li.css('> ul')
|
29
|
-
if ul.size > 0
|
30
|
-
{url: href, text: text, nestedLinks: gather_urls_and_texts(ul)}
|
31
|
-
else
|
32
|
-
{url: href, text: text}
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|