sleeping_king_studios-docs 0.2.0 → 0.3.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/CHANGELOG.md +56 -0
- data/README.md +30 -14
- data/lib/sleeping_king_studios/docs/data/base.rb +24 -4
- data/lib/sleeping_king_studios/docs/data/constant_object.rb +24 -0
- data/lib/sleeping_king_studios/docs/data/metadata.rb +0 -2
- data/lib/sleeping_king_studios/docs/data/method_object.rb +32 -0
- data/lib/sleeping_king_studios/docs/data/module_object.rb +1 -1
- data/lib/sleeping_king_studios/docs/data/namespace_object.rb +26 -2
- data/lib/sleeping_king_studios/docs/data/see_tags/reference_tag.rb +1 -1
- data/lib/sleeping_king_studios/docs/data/types/parser.rb +5 -5
- data/lib/sleeping_king_studios/docs/data/types/type.rb +3 -6
- data/lib/sleeping_king_studios/docs/errors/outdated_documentation.rb +79 -0
- data/lib/sleeping_king_studios/docs/errors/registry_error.rb +13 -0
- data/lib/sleeping_king_studios/docs/errors.rb +4 -0
- data/lib/sleeping_king_studios/docs/jekyll/commands/backfill_versions.rb +177 -0
- data/lib/sleeping_king_studios/docs/jekyll/commands/check.rb +347 -0
- data/lib/sleeping_king_studios/docs/jekyll/commands/clobber.rb +99 -0
- data/lib/sleeping_king_studios/docs/jekyll/commands/document_version.rb +217 -0
- data/lib/sleeping_king_studios/docs/jekyll/commands/generate.rb +202 -0
- data/lib/sleeping_king_studios/docs/jekyll/commands/install.rb +271 -0
- data/lib/sleeping_king_studios/docs/jekyll/commands/install_templates.rb +125 -0
- data/lib/sleeping_king_studios/docs/jekyll/commands/install_workflow.rb +55 -0
- data/lib/sleeping_king_studios/docs/jekyll/commands/reference.rb +158 -0
- data/lib/sleeping_king_studios/docs/jekyll/commands/update.rb +32 -0
- data/lib/sleeping_king_studios/docs/jekyll/commands.rb +44 -0
- data/lib/sleeping_king_studios/docs/jekyll/generators/data_generator.rb +85 -0
- data/lib/sleeping_king_studios/docs/jekyll/generators/reference_generator.rb +40 -0
- data/lib/sleeping_king_studios/docs/jekyll/generators/version_generator.rb +66 -0
- data/lib/sleeping_king_studios/docs/jekyll/generators.rb +15 -0
- data/lib/sleeping_king_studios/docs/jekyll.rb +26 -1
- data/lib/sleeping_king_studios/docs/version.rb +1 -1
- data/lib/sleeping_king_studios/docs/yard/build.rb +42 -0
- data/lib/sleeping_king_studios/docs/{commands → yard}/parse.rb +18 -11
- data/lib/sleeping_king_studios/docs/yard/registry.rb +54 -0
- data/lib/sleeping_king_studios/docs/{registry_query.rb → yard/registry_query.rb} +9 -7
- data/lib/sleeping_king_studios/docs/yard.rb +13 -0
- data/lib/sleeping_king_studios/docs.rb +29 -17
- metadata +66 -83
- data/lib/sleeping_king_studios/docs/commands/generate.rb +0 -268
- data/lib/sleeping_king_studios/docs/commands/generators/base.rb +0 -97
- data/lib/sleeping_king_studios/docs/commands/generators/data_generator.rb +0 -68
- data/lib/sleeping_king_studios/docs/commands/generators/reference_generator.rb +0 -59
- data/lib/sleeping_king_studios/docs/commands/generators.rb +0 -15
- data/lib/sleeping_king_studios/docs/commands/installation/install_jekyll.rb +0 -273
- data/lib/sleeping_king_studios/docs/commands/installation/install_templates.rb +0 -125
- data/lib/sleeping_king_studios/docs/commands/installation/install_workflow.rb +0 -121
- data/lib/sleeping_king_studios/docs/commands/installation.rb +0 -15
- data/lib/sleeping_king_studios/docs/commands/write_file.rb +0 -89
- data/lib/sleeping_king_studios/docs/commands.rb +0 -14
- data/lib/sleeping_king_studios/docs/registry.rb +0 -22
- data/lib/sleeping_king_studios/docs/tasks/base.rb +0 -20
- data/lib/sleeping_king_studios/docs/tasks/generate.rb +0 -39
- data/lib/sleeping_king_studios/docs/tasks/installation/install_jekyll.rb +0 -67
- data/lib/sleeping_king_studios/docs/tasks/installation/install_templates.rb +0 -39
- data/lib/sleeping_king_studios/docs/tasks/installation/install_workflow.rb +0 -53
- data/lib/sleeping_king_studios/docs/tasks/installation.rb +0 -8
- data/lib/sleeping_king_studios/docs/tasks/update.rb +0 -35
- data/lib/sleeping_king_studios/docs/tasks.rb +0 -14
- data/lib/sleeping_king_studios/docs/templates/config.yml.erb +0 -24
- data/lib/sleeping_king_studios/docs/templates/deploy-pages.yml.erb +0 -67
- data/lib/sleeping_king_studios/docs/templates/includes/breadcrumbs.md +0 -7
- data/lib/sleeping_king_studios/docs/templates/includes/reference/attribute.md +0 -23
- data/lib/sleeping_king_studios/docs/templates/includes/reference/attributes/heading.md +0 -15
- data/lib/sleeping_king_studios/docs/templates/includes/reference/class.md +0 -27
- data/lib/sleeping_king_studios/docs/templates/includes/reference/constant.md +0 -8
- data/lib/sleeping_king_studios/docs/templates/includes/reference/constants/heading.md +0 -6
- data/lib/sleeping_king_studios/docs/templates/includes/reference/constants/inherited.md +0 -4
- data/lib/sleeping_king_studios/docs/templates/includes/reference/constants/overview.md +0 -60
- data/lib/sleeping_king_studios/docs/templates/includes/reference/definitions/breadcrumbs.md +0 -21
- data/lib/sleeping_king_studios/docs/templates/includes/reference/definitions/class_attributes.md +0 -9
- data/lib/sleeping_king_studios/docs/templates/includes/reference/definitions/class_methods.md +0 -9
- data/lib/sleeping_king_studios/docs/templates/includes/reference/definitions/constants.md +0 -9
- data/lib/sleeping_king_studios/docs/templates/includes/reference/definitions/constructor.md +0 -12
- data/lib/sleeping_king_studios/docs/templates/includes/reference/definitions/definitions.md +0 -23
- data/lib/sleeping_king_studios/docs/templates/includes/reference/definitions/details.md +0 -34
- data/lib/sleeping_king_studios/docs/templates/includes/reference/definitions/instance_attributes.md +0 -9
- data/lib/sleeping_king_studios/docs/templates/includes/reference/definitions/instance_methods.md +0 -17
- data/lib/sleeping_king_studios/docs/templates/includes/reference/definitions/overview.md +0 -74
- data/lib/sleeping_king_studios/docs/templates/includes/reference/definitions/subclasses.md +0 -10
- data/lib/sleeping_king_studios/docs/templates/includes/reference/definitions/table-of-contents/class_attributes.md +0 -10
- data/lib/sleeping_king_studios/docs/templates/includes/reference/definitions/table-of-contents/class_methods.md +0 -10
- data/lib/sleeping_king_studios/docs/templates/includes/reference/definitions/table-of-contents/constants.md +0 -10
- data/lib/sleeping_king_studios/docs/templates/includes/reference/definitions/table-of-contents/instance_attributes.md +0 -10
- data/lib/sleeping_king_studios/docs/templates/includes/reference/definitions/table-of-contents/instance_methods.md +0 -10
- data/lib/sleeping_king_studios/docs/templates/includes/reference/definitions/table-of-contents/overview.md +0 -41
- data/lib/sleeping_king_studios/docs/templates/includes/reference/definitions/table-of-contents.md +0 -27
- data/lib/sleeping_king_studios/docs/templates/includes/reference/method.md +0 -27
- data/lib/sleeping_king_studios/docs/templates/includes/reference/methods/aliases.md +0 -4
- data/lib/sleeping_king_studios/docs/templates/includes/reference/methods/heading.md +0 -14
- data/lib/sleeping_king_studios/docs/templates/includes/reference/methods/inherited.md +0 -4
- data/lib/sleeping_king_studios/docs/templates/includes/reference/methods/overload.md +0 -18
- data/lib/sleeping_king_studios/docs/templates/includes/reference/methods/overloads.md +0 -12
- data/lib/sleeping_king_studios/docs/templates/includes/reference/methods/overview.md +0 -41
- data/lib/sleeping_king_studios/docs/templates/includes/reference/methods/parameters.md +0 -31
- data/lib/sleeping_king_studios/docs/templates/includes/reference/methods/post_overview.md +0 -51
- data/lib/sleeping_king_studios/docs/templates/includes/reference/methods/raises.md +0 -14
- data/lib/sleeping_king_studios/docs/templates/includes/reference/methods/return_types.md +0 -9
- data/lib/sleeping_king_studios/docs/templates/includes/reference/methods/returns.md +0 -14
- data/lib/sleeping_king_studios/docs/templates/includes/reference/methods/yields.md +0 -42
- data/lib/sleeping_king_studios/docs/templates/includes/reference/module.md +0 -23
- data/lib/sleeping_king_studios/docs/templates/includes/reference/namespace.md +0 -33
- data/lib/sleeping_king_studios/docs/templates/includes/reference/parent_link.md +0 -6
- data/lib/sleeping_king_studios/docs/templates/includes/reference/reference_link.md +0 -7
- data/lib/sleeping_king_studios/docs/templates/includes/reference/see_link.md +0 -7
- data/lib/sleeping_king_studios/docs/templates/includes/reference/type.md +0 -14
- data/lib/sleeping_king_studios/docs/templates/includes/reference/type_list.md +0 -4
- data/lib/sleeping_king_studios/docs/templates/includes/reference/types/array_type.md +0 -1
- data/lib/sleeping_king_studios/docs/templates/includes/reference/types/hash_type.md +0 -1
- data/lib/sleeping_king_studios/docs/templates/includes/reference/types/ordered_type.md +0 -1
- data/lib/sleeping_king_studios/docs/templates/pages/index.md.erb +0 -22
- data/lib/sleeping_king_studios/docs/templates/pages/reference.md.erb +0 -14
- data/lib/sleeping_king_studios/docs/templates/pages/versions.md.erb +0 -13
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'sleeping_king_studios/docs/jekyll/commands'
|
|
4
|
+
|
|
5
|
+
module SleepingKingStudios::Docs::Jekyll::Commands
|
|
6
|
+
# Generates pinned documentation for the specified project version.
|
|
7
|
+
#
|
|
8
|
+
# - Adds the version to the _versions collection.
|
|
9
|
+
# - Generates reference documentation for the version.
|
|
10
|
+
# - Copies all static documentation files to the respective versions/*
|
|
11
|
+
# subdirectory.
|
|
12
|
+
class DocumentVersion < Cuprum::Cli::Command # rubocop:disable Metrics/ClassLength
|
|
13
|
+
dependency :file_system
|
|
14
|
+
dependency :standard_io
|
|
15
|
+
|
|
16
|
+
include Cuprum::Cli::Dependencies::StandardIo::Helpers
|
|
17
|
+
include Cuprum::Cli::Options::Quiet
|
|
18
|
+
include Cuprum::Cli::Options::Verbose
|
|
19
|
+
|
|
20
|
+
argument :version, type: :string, required: true
|
|
21
|
+
|
|
22
|
+
option :docs_path, default: 'docs'
|
|
23
|
+
|
|
24
|
+
option :dry_run, type: :boolean, default: false
|
|
25
|
+
|
|
26
|
+
full_name 'docs:jekyll:document_version'
|
|
27
|
+
|
|
28
|
+
description 'Generates pinned documentation for the specified version'
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def copy_static_file(original_path)
|
|
33
|
+
relative_path = original_path.sub(%r{#{docs_path}/}, '')
|
|
34
|
+
updated_path = File.join(docs_path, 'versions', version, relative_path)
|
|
35
|
+
|
|
36
|
+
contents = file_system.read_file(original_path)
|
|
37
|
+
metadata, text = step { extract_front_matter(contents) }
|
|
38
|
+
metadata = update_metadata(metadata:, relative_path:)
|
|
39
|
+
contents = generate_contents(metadata:, text:)
|
|
40
|
+
|
|
41
|
+
files = step { write_static_file(contents:, updated_path:) }
|
|
42
|
+
|
|
43
|
+
@files.concat(files)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def copy_static_files
|
|
47
|
+
say "\nCopying static documentation..."
|
|
48
|
+
say("\n", verbose: true)
|
|
49
|
+
|
|
50
|
+
find_static_docs.each { |file_path| copy_static_file(file_path) }
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def default_breadcrumbs_for(relative_path)
|
|
54
|
+
*dir_path, _ = relative_path.split(File::SEPARATOR)
|
|
55
|
+
|
|
56
|
+
return [] if dir_path.empty?
|
|
57
|
+
|
|
58
|
+
dir_path
|
|
59
|
+
.each
|
|
60
|
+
.map do |segment, index|
|
|
61
|
+
name = tools.string_tools.camelize(segment.tr('-_', ''))
|
|
62
|
+
path = "#{File::SEPARATOR}#{File.join(dir_path[0..index])}"
|
|
63
|
+
|
|
64
|
+
{ 'name' => name, 'path' => path }
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def exclude_static_file?(file_path)
|
|
69
|
+
return false if file_path == "#{docs_path}/reference/index.md"
|
|
70
|
+
|
|
71
|
+
file_path.start_with?("#{docs_path}/_includes/") ||
|
|
72
|
+
file_path.start_with?("#{docs_path}/reference") ||
|
|
73
|
+
file_path.start_with?("#{docs_path}/versions")
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def extract_front_matter(contents)
|
|
77
|
+
return [{}, contents] unless contents.start_with?("---\n")
|
|
78
|
+
|
|
79
|
+
match = /^---\n$/.match(contents[4..])
|
|
80
|
+
|
|
81
|
+
return [{}, contents] unless match
|
|
82
|
+
|
|
83
|
+
text = match.post_match
|
|
84
|
+
yaml = YAML.safe_load(match.pre_match) || {}
|
|
85
|
+
|
|
86
|
+
[yaml, text]
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def generate_contents(metadata:, text:)
|
|
90
|
+
"#{YAML.safe_dump(metadata)}---\n#{text}"
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def generate_reference_files # rubocop:disable Metrics/MethodLength
|
|
94
|
+
say "\nGenerating data and reference files:"
|
|
95
|
+
say("\n", verbose: true)
|
|
96
|
+
|
|
97
|
+
files = step do
|
|
98
|
+
SleepingKingStudios::Docs::Jekyll::Commands::Generate
|
|
99
|
+
.new(file_system:, standard_io:)
|
|
100
|
+
.call(
|
|
101
|
+
docs_path:,
|
|
102
|
+
dry_run: dry_run?,
|
|
103
|
+
quiet: quiet?,
|
|
104
|
+
verbose: verbose?,
|
|
105
|
+
version:
|
|
106
|
+
)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
@files.concat(files)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def generate_version # rubocop:disable Metrics/MethodLength
|
|
113
|
+
say "\nGenerating version file:"
|
|
114
|
+
say("\n", verbose: true)
|
|
115
|
+
|
|
116
|
+
files = step do
|
|
117
|
+
SleepingKingStudios::Docs::Jekyll::Generators::VersionGenerator
|
|
118
|
+
.new(
|
|
119
|
+
file_system:,
|
|
120
|
+
standard_io:,
|
|
121
|
+
docs_path:,
|
|
122
|
+
dry_run: dry_run?,
|
|
123
|
+
quiet: quiet?,
|
|
124
|
+
verbose: verbose?,
|
|
125
|
+
version:
|
|
126
|
+
)
|
|
127
|
+
.call
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
@files.concat(files)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def find_static_docs
|
|
134
|
+
file_system
|
|
135
|
+
.each_file("#{docs_path}/**/*.md")
|
|
136
|
+
.reject { |file_path| exclude_static_file?(file_path) }
|
|
137
|
+
.to_a
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def process
|
|
141
|
+
say "Generating pinned documentation for version #{version}"
|
|
142
|
+
|
|
143
|
+
@files = []
|
|
144
|
+
|
|
145
|
+
step { generate_reference_files }
|
|
146
|
+
|
|
147
|
+
step { generate_version }
|
|
148
|
+
|
|
149
|
+
step { copy_static_files }
|
|
150
|
+
|
|
151
|
+
say "\nSuccess!"
|
|
152
|
+
|
|
153
|
+
@files
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def top_level_breadcrumb?(obj)
|
|
157
|
+
obj.is_a?(Hash) && obj['path'] == File::SEPARATOR
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def version_breadcrumbs # rubocop:disable Metrics/MethodLength
|
|
161
|
+
@version_breadcrumbs ||= [
|
|
162
|
+
{
|
|
163
|
+
'name' => 'Documentation',
|
|
164
|
+
'path' => File::SEPARATOR
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
'name' => 'Versions',
|
|
168
|
+
'path' => "#{File::SEPARATOR}versions"
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
'name' => "Version #{version}",
|
|
172
|
+
'path' => "#{File::SEPARATOR}#{File.join('versions', version)}"
|
|
173
|
+
}
|
|
174
|
+
]
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def update_breadcrumbs(breadcrumbs:, relative_path:)
|
|
178
|
+
prefix = "#{File::SEPARATOR}#{File.join('versions', version)}"
|
|
179
|
+
breadcrumbs = breadcrumbs[1..] if top_level_breadcrumb?(breadcrumbs.first)
|
|
180
|
+
breadcrumbs = breadcrumbs.map do |hsh|
|
|
181
|
+
hsh.merge('path' => File.join(prefix, hsh['path']))
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
if breadcrumbs.empty? && relative_path == 'index.md'
|
|
185
|
+
return version_breadcrumbs[...-1]
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
version_breadcrumbs + breadcrumbs
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def update_metadata(metadata:, relative_path:)
|
|
192
|
+
breadcrumbs = update_breadcrumbs(
|
|
193
|
+
breadcrumbs: metadata.fetch(
|
|
194
|
+
'breadcrumbs',
|
|
195
|
+
default_breadcrumbs_for(relative_path)
|
|
196
|
+
),
|
|
197
|
+
relative_path:
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
metadata.merge('breadcrumbs' => breadcrumbs, 'version' => version)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def write_static_file(contents:, updated_path:) # rubocop:disable Metrics/MethodLength
|
|
204
|
+
Cuprum::Cli::Files::Generators::BasicGenerator
|
|
205
|
+
.new(
|
|
206
|
+
file_system:,
|
|
207
|
+
standard_io:,
|
|
208
|
+
contents:,
|
|
209
|
+
dry_run: dry_run?,
|
|
210
|
+
file_path: updated_path,
|
|
211
|
+
quiet: quiet?,
|
|
212
|
+
verbose: verbose?
|
|
213
|
+
)
|
|
214
|
+
.call
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'sleeping_king_studios/docs/jekyll/commands'
|
|
4
|
+
|
|
5
|
+
module SleepingKingStudios::Docs::Jekyll::Commands
|
|
6
|
+
# Generates new reference documentation.
|
|
7
|
+
class Generate < SleepingKingStudios::Docs::Jekyll::Commands::Reference # rubocop:disable Metrics/ClassLength
|
|
8
|
+
full_name 'docs:jekyll:generate'
|
|
9
|
+
|
|
10
|
+
description 'Generates reference documentation for the current version'
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
attr_reader :errors
|
|
15
|
+
|
|
16
|
+
attr_reader :files
|
|
17
|
+
|
|
18
|
+
attr_reader :registry
|
|
19
|
+
|
|
20
|
+
def build_command
|
|
21
|
+
@build_command ||= SleepingKingStudios::Docs::Yard::Build.new
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def clear_data_directory(path) # rubocop:disable Metrics/MethodLength
|
|
25
|
+
return unless file_system.directory?(path)
|
|
26
|
+
|
|
27
|
+
if dry_run?
|
|
28
|
+
step { ensure_data_directory_empty(path) }
|
|
29
|
+
|
|
30
|
+
return
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
each_data_directory(path) do |child|
|
|
34
|
+
file_system.delete_directory(child, recursive: true)
|
|
35
|
+
end
|
|
36
|
+
rescue Cuprum::Cli::Dependencies::FileSystem::FileError => exception
|
|
37
|
+
error = SleepingKingStudios::Docs::Errors::FileError.new(
|
|
38
|
+
message: exception.message,
|
|
39
|
+
path:
|
|
40
|
+
)
|
|
41
|
+
failure(error)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def clear_directories
|
|
45
|
+
step { clear_reference_directory }
|
|
46
|
+
|
|
47
|
+
step { clear_data_directory(class_data_directory) }
|
|
48
|
+
step { clear_data_directory(constant_data_directory) }
|
|
49
|
+
step { clear_data_directory(method_data_directory) }
|
|
50
|
+
step { clear_data_directory(module_data_directory) }
|
|
51
|
+
step { clear_data_directory(namespace_data_directory) }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def clear_reference_directory # rubocop:disable Metrics/MethodLength
|
|
55
|
+
return unless file_system.directory?(reference_directory)
|
|
56
|
+
|
|
57
|
+
if dry_run?
|
|
58
|
+
step { ensure_reference_directory_empty }
|
|
59
|
+
|
|
60
|
+
return
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
each_reference_directory do |path|
|
|
64
|
+
file_system.delete_directory(path, recursive: true)
|
|
65
|
+
end
|
|
66
|
+
rescue Cuprum::Cli::Dependencies::FileSystem::FileError => exception
|
|
67
|
+
error = SleepingKingStudios::Docs::Errors::FileError.new(
|
|
68
|
+
message: exception.message,
|
|
69
|
+
path: reference_directory
|
|
70
|
+
)
|
|
71
|
+
failure(error)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def ensure_data_directory_empty(path)
|
|
75
|
+
matching = each_data_file(path).first
|
|
76
|
+
|
|
77
|
+
return unless matching
|
|
78
|
+
|
|
79
|
+
path = File.dirname(matching)
|
|
80
|
+
|
|
81
|
+
message = "unable to delete directory #{path} - directory is not empty"
|
|
82
|
+
error = SleepingKingStudios::Docs::Errors::FileError.new(
|
|
83
|
+
message:,
|
|
84
|
+
path:
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
failure(error)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def ensure_reference_directory_empty # rubocop:disable Metrics/MethodLength
|
|
91
|
+
matching = each_reference_file.first
|
|
92
|
+
|
|
93
|
+
return unless matching
|
|
94
|
+
|
|
95
|
+
path = File.dirname(matching)
|
|
96
|
+
|
|
97
|
+
message =
|
|
98
|
+
"unable to delete directory #{path} - directory is " \
|
|
99
|
+
'not empty'
|
|
100
|
+
error = SleepingKingStudios::Docs::Errors::FileError.new(
|
|
101
|
+
message:,
|
|
102
|
+
path:
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
failure(error)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def generator_for(object)
|
|
109
|
+
namespace = SleepingKingStudios::Docs::Jekyll::Generators
|
|
110
|
+
generator_class =
|
|
111
|
+
if object.is_a?(SleepingKingStudios::Docs::Data::ModuleObject)
|
|
112
|
+
namespace::ReferenceGenerator
|
|
113
|
+
else
|
|
114
|
+
namespace::DataGenerator
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
generator_class.new(object:, **generator_options)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def generator_options
|
|
121
|
+
@generator_options ||= {
|
|
122
|
+
file_system:,
|
|
123
|
+
standard_io:,
|
|
124
|
+
docs_path:,
|
|
125
|
+
dry_run: dry_run?,
|
|
126
|
+
quiet: quiet?,
|
|
127
|
+
verbose: verbose?,
|
|
128
|
+
version:
|
|
129
|
+
}
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def handle_generator_result
|
|
133
|
+
result = yield
|
|
134
|
+
|
|
135
|
+
if result.success?
|
|
136
|
+
files.concat(result.value)
|
|
137
|
+
|
|
138
|
+
return
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
errors << result.error
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def parse_registry
|
|
145
|
+
@registry = step do
|
|
146
|
+
SleepingKingStudios::Docs::Yard::Parse.new.call
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
SleepingKingStudios::Docs::Yard::Registry
|
|
150
|
+
.provider
|
|
151
|
+
.set(:registry, registry)
|
|
152
|
+
rescue Plumbum::Errors::ImmutableError => exception
|
|
153
|
+
message = "#{exception.class}: #{exception.message}"
|
|
154
|
+
error = SleepingKingStudios::Docs::Errors::RegistryError.new(message:)
|
|
155
|
+
|
|
156
|
+
failure(error)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def process # rubocop:disable Metrics/MethodLength
|
|
160
|
+
@files = []
|
|
161
|
+
@errors = []
|
|
162
|
+
|
|
163
|
+
step { clear_directories }
|
|
164
|
+
|
|
165
|
+
step { parse_registry }
|
|
166
|
+
|
|
167
|
+
registry.each do |native|
|
|
168
|
+
data = step { build_command.call(native) }
|
|
169
|
+
|
|
170
|
+
next unless data.public?
|
|
171
|
+
|
|
172
|
+
generator = generator_for(data)
|
|
173
|
+
|
|
174
|
+
handle_generator_result { generator.call }
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
report_errors
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def report_errors # rubocop:disable Metrics/MethodLength
|
|
181
|
+
if errors.empty?
|
|
182
|
+
say 'Success!'
|
|
183
|
+
|
|
184
|
+
return files
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
warn 'Failures:'
|
|
188
|
+
warn "\n"
|
|
189
|
+
|
|
190
|
+
errors.each do |error|
|
|
191
|
+
warn " - Unable to generate file #{error.path} - #{error.message}"
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
warn "\n"
|
|
195
|
+
|
|
196
|
+
message = 'unable to generate documentation files'
|
|
197
|
+
error = Cuprum::Errors::MultipleErrors.new(errors:, message:)
|
|
198
|
+
|
|
199
|
+
failure(error)
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
end
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'cuprum/cli'
|
|
4
|
+
|
|
5
|
+
require 'sleeping_king_studios/docs/jekyll/commands'
|
|
6
|
+
|
|
7
|
+
module SleepingKingStudios::Docs::Jekyll::Commands
|
|
8
|
+
# Installs the Jekyll application.
|
|
9
|
+
class Install < Cuprum::Cli::Command # rubocop:disable Metrics/ClassLength
|
|
10
|
+
dependency :file_system
|
|
11
|
+
dependency :standard_io
|
|
12
|
+
|
|
13
|
+
include Cuprum::Cli::Dependencies::StandardIo::Helpers
|
|
14
|
+
include Cuprum::Cli::Options::Quiet
|
|
15
|
+
include Cuprum::Cli::Options::Verbose
|
|
16
|
+
|
|
17
|
+
TEMPLATES_PATH = SleepingKingStudios::Docs::Jekyll::Commands.templates_path
|
|
18
|
+
private_constant :TEMPLATES_PATH
|
|
19
|
+
|
|
20
|
+
# Generator for writing the Jekyll static pages.
|
|
21
|
+
class Generator < Cuprum::Cli::Files::Generator
|
|
22
|
+
output '%<docs_path>s/_config.yml',
|
|
23
|
+
key: :config,
|
|
24
|
+
template: File.join(TEMPLATES_PATH, 'config.yml.erb')
|
|
25
|
+
|
|
26
|
+
output '%<docs_path>s/_layouts/page.html',
|
|
27
|
+
key: :layout,
|
|
28
|
+
template: File.join(TEMPLATES_PATH, 'layouts', 'page.html.erb')
|
|
29
|
+
|
|
30
|
+
output '%<docs_path>s/index.md',
|
|
31
|
+
key: :index,
|
|
32
|
+
template: File.join(TEMPLATES_PATH, 'pages', 'index.md.erb')
|
|
33
|
+
|
|
34
|
+
output '%<docs_path>s/reference/index.md',
|
|
35
|
+
key: :reference,
|
|
36
|
+
template: File.join(TEMPLATES_PATH, 'pages', 'reference.md.erb')
|
|
37
|
+
|
|
38
|
+
output '%<docs_path>s/versions/index.md',
|
|
39
|
+
key: :versions,
|
|
40
|
+
template: File.join(TEMPLATES_PATH, 'pages', 'versions.md.erb')
|
|
41
|
+
|
|
42
|
+
option :docs_path, default: 'docs'
|
|
43
|
+
|
|
44
|
+
option :project_description, default: ''
|
|
45
|
+
|
|
46
|
+
option :project_name, default: 'Project Name'
|
|
47
|
+
|
|
48
|
+
option :project_repository, default: ''
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
full_name 'docs:jekyll:install'
|
|
52
|
+
|
|
53
|
+
description 'Installs the Jekyll application'
|
|
54
|
+
|
|
55
|
+
option :docs_path, type: :string, default: 'docs'
|
|
56
|
+
|
|
57
|
+
option :dry_run, type: :boolean, default: false
|
|
58
|
+
|
|
59
|
+
option :gemfile, type: :boolean, default: true
|
|
60
|
+
|
|
61
|
+
option :gitignore, type: :boolean, default: true
|
|
62
|
+
|
|
63
|
+
option :templates, type: :boolean, default: true
|
|
64
|
+
|
|
65
|
+
option :workflow, type: :boolean, default: false
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
attr_reader :errors
|
|
70
|
+
|
|
71
|
+
attr_reader :output_paths
|
|
72
|
+
|
|
73
|
+
def create_directory
|
|
74
|
+
return if file_system.directory?(docs_path)
|
|
75
|
+
|
|
76
|
+
say "Generating directory #{docs_path}..."
|
|
77
|
+
say("\n", verbose: true)
|
|
78
|
+
|
|
79
|
+
file_system.create_directory(docs_path, recursive: true) unless dry_run?
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def create_gemfile
|
|
83
|
+
gems = included_gems.map { |k, v| " gem '#{k}', '#{v}'" }.join("\n")
|
|
84
|
+
contents = <<~GEMFILE
|
|
85
|
+
# frozen_string_literal: true
|
|
86
|
+
|
|
87
|
+
source 'https://rubygems.org'
|
|
88
|
+
|
|
89
|
+
group: :docs do
|
|
90
|
+
#{gems}
|
|
91
|
+
end
|
|
92
|
+
GEMFILE
|
|
93
|
+
|
|
94
|
+
say 'Generating Gemfile...'
|
|
95
|
+
say("\n#{indent(contents, 2)}\n", verbose: true)
|
|
96
|
+
|
|
97
|
+
file_system.write_file('Gemfile', contents) unless dry_run?
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def create_gitignore
|
|
101
|
+
contents = "# Ignore Jekyll site and temporary files.\n"
|
|
102
|
+
|
|
103
|
+
ignored_paths.each { |path| contents = "#{contents}#{path}\n" }
|
|
104
|
+
|
|
105
|
+
say 'Generating .gitignore...'
|
|
106
|
+
say("\n#{indent(contents, 2)}\n", verbose: true)
|
|
107
|
+
|
|
108
|
+
file_system.write_file('.gitignore', contents) unless dry_run?
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def create_static_files # rubocop:disable Metrics/MethodLength
|
|
112
|
+
static_files = step do
|
|
113
|
+
Generator
|
|
114
|
+
.new(
|
|
115
|
+
file_system:,
|
|
116
|
+
standard_io:,
|
|
117
|
+
docs_path:,
|
|
118
|
+
dry_run: dry_run?,
|
|
119
|
+
directories: true,
|
|
120
|
+
quiet: quiet?,
|
|
121
|
+
verbose: verbose?
|
|
122
|
+
)
|
|
123
|
+
.call
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
output_paths.concat(static_files)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def handle_file_error(file_path)
|
|
130
|
+
yield
|
|
131
|
+
|
|
132
|
+
success(file_path)
|
|
133
|
+
rescue Cuprum::Cli::Dependencies::FileSystem::FileError => exception
|
|
134
|
+
warn(" ! #{exception.message}")
|
|
135
|
+
|
|
136
|
+
error = Cuprum::Cli::Files::Errors::FileNotWriteable.new(
|
|
137
|
+
file_path:,
|
|
138
|
+
message: exception.message
|
|
139
|
+
)
|
|
140
|
+
failure(error)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def ignored_paths
|
|
144
|
+
[
|
|
145
|
+
"#{docs_path}/_site",
|
|
146
|
+
"#{docs_path}/.sass-cache",
|
|
147
|
+
"#{docs_path}/.jekyll-cache",
|
|
148
|
+
"#{docs_path}/.jekyll-metadata",
|
|
149
|
+
'vendor'
|
|
150
|
+
]
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def included_gems
|
|
154
|
+
{
|
|
155
|
+
'jekyll' => '~> 4.4',
|
|
156
|
+
'kramdown-parser-gfm' => '~> 1.1',
|
|
157
|
+
'webrick' => '~> 1.8'
|
|
158
|
+
}
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def indent(str, count) = tools.string_tools.indent(str, count)
|
|
162
|
+
|
|
163
|
+
def install_templates # rubocop:disable Metrics/MethodLength
|
|
164
|
+
return unless templates?
|
|
165
|
+
|
|
166
|
+
template_files = step do
|
|
167
|
+
SleepingKingStudios::Docs::Jekyll::Commands::InstallTemplates
|
|
168
|
+
.new(file_system:, standard_io:)
|
|
169
|
+
.call(
|
|
170
|
+
docs_path:,
|
|
171
|
+
dry_run: dry_run?,
|
|
172
|
+
quiet: quiet?,
|
|
173
|
+
verbose: verbose?
|
|
174
|
+
)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
say("\n", verbose: true)
|
|
178
|
+
|
|
179
|
+
output_paths.concat(template_files)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def install_workflow # rubocop:disable Metrics/MethodLength
|
|
183
|
+
return unless workflow?
|
|
184
|
+
|
|
185
|
+
workflow_files = step do
|
|
186
|
+
SleepingKingStudios::Docs::Jekyll::Commands::InstallWorkflow
|
|
187
|
+
.new(file_system:, standard_io:)
|
|
188
|
+
.call(
|
|
189
|
+
dry_run: dry_run?,
|
|
190
|
+
quiet: quiet?,
|
|
191
|
+
verbose: verbose?
|
|
192
|
+
)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
output_paths.concat(workflow_files)
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def merge_gemfile # rubocop:disable Metrics/AbcSize
|
|
199
|
+
contents = file_system.read_file('Gemfile')
|
|
200
|
+
existing = contents.each_line.map(&:strip)
|
|
201
|
+
added = included_gems.reject { |k, _| existing.include?("gem '#{k}'") }
|
|
202
|
+
|
|
203
|
+
return if added.empty?
|
|
204
|
+
|
|
205
|
+
gems = added.map { |k, v| " gem '#{k}', '#{v}'" }.join("\n")
|
|
206
|
+
|
|
207
|
+
contents << "\n" unless contents.end_with?("\n\n")
|
|
208
|
+
contents << "group :docs do\n#{gems}\nend\n"
|
|
209
|
+
|
|
210
|
+
say 'Updating Gemfile...'
|
|
211
|
+
say("\n#{indent(contents, 2)}\n", verbose: true)
|
|
212
|
+
|
|
213
|
+
file_system.write_file('Gemfile', contents) unless dry_run?
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def merge_gitignore # rubocop:disable Metrics/AbcSize
|
|
217
|
+
contents = file_system.read_file('.gitignore')
|
|
218
|
+
existing = contents.each_line.map(&:strip)
|
|
219
|
+
added = ignored_paths.reject { |path| existing.include?(path) }
|
|
220
|
+
|
|
221
|
+
return if added.empty?
|
|
222
|
+
|
|
223
|
+
contents << "\n" unless contents.end_with?("\n\n")
|
|
224
|
+
contents << "# Ignore Jekyll site and temporary files.\n"
|
|
225
|
+
|
|
226
|
+
added.each { |path| contents << path << "\n" }
|
|
227
|
+
|
|
228
|
+
say 'Updating .gitignore...'
|
|
229
|
+
say("\n#{indent(contents, 2)}\n", verbose: true)
|
|
230
|
+
|
|
231
|
+
file_system.write_file('.gitignore', contents) unless dry_run?
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def process
|
|
235
|
+
@output_paths = []
|
|
236
|
+
|
|
237
|
+
step { update_gitignore }
|
|
238
|
+
step { update_gemfile }
|
|
239
|
+
step { create_directory }
|
|
240
|
+
step { create_static_files }
|
|
241
|
+
step { install_templates }
|
|
242
|
+
step { install_workflow }
|
|
243
|
+
|
|
244
|
+
output_paths
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def update_gemfile
|
|
248
|
+
return unless gemfile?
|
|
249
|
+
|
|
250
|
+
step do
|
|
251
|
+
handle_file_error('Gemfile') do
|
|
252
|
+
file_system.file?('Gemfile') ? merge_gemfile : create_gemfile
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
output_paths << 'Gemfile'
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def update_gitignore
|
|
260
|
+
return unless gitignore?
|
|
261
|
+
|
|
262
|
+
step do
|
|
263
|
+
handle_file_error('.gitignore') do
|
|
264
|
+
file_system.file?('.gitignore') ? merge_gitignore : create_gitignore
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
output_paths << '.gitignore'
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
end
|