bookbindery 6.0.0 → 7.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|