sleeping_king_studios-docs 0.2.1 → 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 +52 -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/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 +2 -2
- 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 +54 -86
- 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,347 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'yaml'
|
|
4
|
+
|
|
5
|
+
require 'sleeping_king_studios/docs/jekyll/commands'
|
|
6
|
+
|
|
7
|
+
module SleepingKingStudios::Docs::Jekyll::Commands
|
|
8
|
+
# Checks whether the current documentation is up to date.
|
|
9
|
+
class Check < SleepingKingStudios::Docs::Jekyll::Commands::Reference # rubocop:disable Metrics/ClassLength
|
|
10
|
+
full_name 'docs:jekyll:check'
|
|
11
|
+
|
|
12
|
+
description 'Checks whether the current documentation is up to date'
|
|
13
|
+
|
|
14
|
+
option :inspect_changes,
|
|
15
|
+
aliases: %i[inspect],
|
|
16
|
+
type: :boolean,
|
|
17
|
+
default: false
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
attr_reader :changed_files
|
|
22
|
+
|
|
23
|
+
attr_reader :extra_files
|
|
24
|
+
|
|
25
|
+
attr_reader :missing_files
|
|
26
|
+
|
|
27
|
+
attr_reader :registry
|
|
28
|
+
|
|
29
|
+
def build_command
|
|
30
|
+
@build_command ||= SleepingKingStudios::Docs::Yard::Build.new
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def collection_path_for(data)
|
|
34
|
+
data_type = data_type_for(data)
|
|
35
|
+
|
|
36
|
+
data_collections[data_type]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def compare_files(actual:, expected:)
|
|
40
|
+
# Skip the full analysis if all files are matching.
|
|
41
|
+
return if actual == expected
|
|
42
|
+
|
|
43
|
+
missing = find_missing_files(actual:, expected:)
|
|
44
|
+
extra = find_extra_files(actual:, expected:)
|
|
45
|
+
matching = expected.except(*missing).reject { |_, value| value == true }
|
|
46
|
+
changed = find_changed_files(actual:, matching:)
|
|
47
|
+
|
|
48
|
+
@missing_files.concat(missing)
|
|
49
|
+
@extra_files.concat(extra)
|
|
50
|
+
@changed_files.concat(changed)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def data_collections
|
|
54
|
+
@data_collections ||= Hash.new do |hsh, data_type|
|
|
55
|
+
hsh[data_type] = tools.string_tools.pluralize(data_type)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def data_file_for(data)
|
|
60
|
+
"#{data_path_for(data)}/#{data.data_path}.yml"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def data_path_for(data)
|
|
64
|
+
collection_path = collection_path_for(data)
|
|
65
|
+
|
|
66
|
+
if version
|
|
67
|
+
File.join(docs_path, "_#{collection_path}", "version--#{version}")
|
|
68
|
+
else
|
|
69
|
+
File.join(docs_path, "_#{collection_path}")
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def data_type_for(data)
|
|
74
|
+
data
|
|
75
|
+
.class
|
|
76
|
+
.name
|
|
77
|
+
.split('::')
|
|
78
|
+
.last
|
|
79
|
+
.sub(/Object\z/, '')
|
|
80
|
+
.then { |str| tools.string_tools.underscore(str) }
|
|
81
|
+
.then { |str| str == 'root' ? 'namespace' : str }
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def file_not_found_error(**)
|
|
85
|
+
SleepingKingStudios::Docs::Errors::FileError.new(**)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def find_changed_files(actual:, matching:)
|
|
89
|
+
return [] if matching.empty?
|
|
90
|
+
|
|
91
|
+
matching
|
|
92
|
+
.reject { |key, value| value == actual[key] }
|
|
93
|
+
.keys
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def find_data_files
|
|
97
|
+
[
|
|
98
|
+
*each_data_file(class_data_directory),
|
|
99
|
+
*each_data_file(constant_data_directory),
|
|
100
|
+
*each_data_file(method_data_directory),
|
|
101
|
+
*each_data_file(module_data_directory),
|
|
102
|
+
*each_data_file(namespace_data_directory)
|
|
103
|
+
]
|
|
104
|
+
.to_h { |file_path| [file_path, step { read_checksum(file_path) }] }
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def find_expected_files
|
|
108
|
+
expected_data = {}
|
|
109
|
+
expected_reference = {}
|
|
110
|
+
|
|
111
|
+
registry.each do |native|
|
|
112
|
+
data = step { build_command.call(native) }
|
|
113
|
+
|
|
114
|
+
next unless data.public?
|
|
115
|
+
|
|
116
|
+
expected_data[data_file_for(data)] = data.checksum
|
|
117
|
+
|
|
118
|
+
next unless reference?(data)
|
|
119
|
+
|
|
120
|
+
expected_reference[reference_file_for(data)] = true
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
[expected_data, expected_reference]
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def find_extra_files(actual:, expected:)
|
|
127
|
+
actual.each_key.reject { |key| expected.key?(key) }
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def find_missing_files(actual:, expected:)
|
|
131
|
+
expected.each_key.reject { |key| actual.key?(key) }
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def find_native_object_for(file_path)
|
|
135
|
+
registry.each do |native|
|
|
136
|
+
data = step { build_command.call(native) }
|
|
137
|
+
|
|
138
|
+
next unless data.public?
|
|
139
|
+
|
|
140
|
+
next unless file_path == data_file_for(data)
|
|
141
|
+
|
|
142
|
+
return data
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# :nocov:
|
|
146
|
+
nil
|
|
147
|
+
# :nocov:
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def find_reference_files
|
|
151
|
+
each_reference_file.to_h { |file_path| [file_path, true] }
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def generate_inspect_contents_for(object, mock_fs:)
|
|
155
|
+
SleepingKingStudios::Docs::Jekyll::Generators::DataGenerator
|
|
156
|
+
.new(object:, file_system: mock_fs, standard_io:, quiet: true)
|
|
157
|
+
.call
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def indent(contents)
|
|
161
|
+
contents
|
|
162
|
+
.each_line
|
|
163
|
+
.map do |line|
|
|
164
|
+
next "\n" if line == "\n"
|
|
165
|
+
|
|
166
|
+
" #{line}"
|
|
167
|
+
end
|
|
168
|
+
.join
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def inspect_changed_files # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
172
|
+
return unless inspect_changes? && !changed_files.empty?
|
|
173
|
+
|
|
174
|
+
say "\n"
|
|
175
|
+
say '-' * 80
|
|
176
|
+
say "\n"
|
|
177
|
+
|
|
178
|
+
mock_fs = Cuprum::Cli::Dependencies::FileSystem::Mock.new
|
|
179
|
+
|
|
180
|
+
changed_files.each do |file_path|
|
|
181
|
+
data = find_native_object_for(file_path)
|
|
182
|
+
result = generate_inspect_contents_for(data, mock_fs:)
|
|
183
|
+
|
|
184
|
+
next unless result.success?
|
|
185
|
+
|
|
186
|
+
say "Changed file #{file_path}:\n\n"
|
|
187
|
+
|
|
188
|
+
contents = mock_fs.read(file_path)
|
|
189
|
+
|
|
190
|
+
say indent(contents)
|
|
191
|
+
say "\n"
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def outdated_documentation_error
|
|
196
|
+
SleepingKingStudios::Docs::Errors::OutdatedDocumentation.new(
|
|
197
|
+
docs_path:,
|
|
198
|
+
version:,
|
|
199
|
+
changed_files:,
|
|
200
|
+
extra_files:,
|
|
201
|
+
missing_files:
|
|
202
|
+
)
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def parse_registry # rubocop:disable Metrics/MethodLength
|
|
206
|
+
@registry = step do
|
|
207
|
+
SleepingKingStudios::Docs::Yard::Parse.new.call
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
SleepingKingStudios::Docs::Yard::Registry
|
|
211
|
+
.provider
|
|
212
|
+
.set(:registry, registry)
|
|
213
|
+
|
|
214
|
+
registry
|
|
215
|
+
rescue Plumbum::Errors::ImmutableError => exception
|
|
216
|
+
message = "#{exception.class}: #{exception.message}"
|
|
217
|
+
error = SleepingKingStudios::Docs::Errors::RegistryError.new(message:)
|
|
218
|
+
|
|
219
|
+
failure(error)
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def process # rubocop:disable Metrics/MethodLength
|
|
223
|
+
say "Checking documentation for #{version_string}..."
|
|
224
|
+
say "\n", verbose: true
|
|
225
|
+
|
|
226
|
+
@missing_files = []
|
|
227
|
+
@extra_files = []
|
|
228
|
+
@changed_files = []
|
|
229
|
+
data_files = step { find_data_files }
|
|
230
|
+
reference_files = step { find_reference_files }
|
|
231
|
+
|
|
232
|
+
step { parse_registry }
|
|
233
|
+
|
|
234
|
+
expected_data_files, expected_reference_files = step do
|
|
235
|
+
find_expected_files
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
compare_files(actual: data_files, expected: expected_data_files)
|
|
239
|
+
compare_files(actual: reference_files, expected: expected_reference_files)
|
|
240
|
+
|
|
241
|
+
report_results
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def read_checksum(file_path) # rubocop:disable Metrics/MethodLength
|
|
245
|
+
raw = file_system.read(file_path)
|
|
246
|
+
yaml = YAML.safe_load(raw)
|
|
247
|
+
|
|
248
|
+
yaml.fetch('checksum') do
|
|
249
|
+
warn_missing_checksum(file_path)
|
|
250
|
+
|
|
251
|
+
nil
|
|
252
|
+
end
|
|
253
|
+
rescue Cuprum::Cli::Dependencies::FileSystem::FileError => exception
|
|
254
|
+
failure(file_not_found_error(message: exception.message, path: file_path))
|
|
255
|
+
rescue Psych::SyntaxError => exception
|
|
256
|
+
message =
|
|
257
|
+
"unable to parse file - error occurred on line #{exception.line}, " \
|
|
258
|
+
"column #{exception.column}"
|
|
259
|
+
|
|
260
|
+
failure(file_not_found_error(message:, path: file_path))
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
def reference?(data)
|
|
264
|
+
data.is_a?(SleepingKingStudios::Docs::Data::ModuleObject)
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def reference_file_for(data)
|
|
268
|
+
"#{reference_path}/#{data.data_path}.md"
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def reference_path
|
|
272
|
+
@reference_path ||=
|
|
273
|
+
if version
|
|
274
|
+
File.join(docs_path, 'versions', version, 'reference')
|
|
275
|
+
else
|
|
276
|
+
File.join(docs_path, 'reference')
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
def report_changed_files
|
|
281
|
+
return if changed_files.empty?
|
|
282
|
+
|
|
283
|
+
say 'Changed files:', verbose: true
|
|
284
|
+
say "\n", verbose: true
|
|
285
|
+
|
|
286
|
+
changed_files.each do |file_path|
|
|
287
|
+
say " - Changed file #{file_path}"
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
say "\n", verbose: true
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
def report_extra_files
|
|
294
|
+
return if extra_files.empty?
|
|
295
|
+
|
|
296
|
+
say 'Extra files:', verbose: true
|
|
297
|
+
say "\n", verbose: true
|
|
298
|
+
|
|
299
|
+
extra_files.each do |file_path|
|
|
300
|
+
say " - Extra file #{file_path}"
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
say "\n", verbose: true
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
def report_missing_files
|
|
307
|
+
return if missing_files.empty?
|
|
308
|
+
|
|
309
|
+
say 'Missing files:', verbose: true
|
|
310
|
+
say "\n", verbose: true
|
|
311
|
+
|
|
312
|
+
missing_files.each do |file_path|
|
|
313
|
+
say " - Missing file #{file_path}"
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
say "\n", verbose: true
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
def report_results
|
|
320
|
+
if changed_files.empty? && missing_files.empty? && extra_files.empty?
|
|
321
|
+
say 'Success!'
|
|
322
|
+
|
|
323
|
+
return []
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
report_missing_files
|
|
327
|
+
report_extra_files
|
|
328
|
+
report_changed_files
|
|
329
|
+
|
|
330
|
+
say 'Failure!'
|
|
331
|
+
|
|
332
|
+
inspect_changed_files
|
|
333
|
+
|
|
334
|
+
failure(outdated_documentation_error)
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
def version_string
|
|
338
|
+
version ? "version #{version}" : 'current version'
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
def warn_missing_checksum(file_path)
|
|
342
|
+
message = "Warning: file #{file_path} does not have a valid checksum\n"
|
|
343
|
+
|
|
344
|
+
standard_io.write_error(message)
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
end
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'sleeping_king_studios/docs/jekyll/commands'
|
|
4
|
+
|
|
5
|
+
module SleepingKingStudios::Docs::Jekyll::Commands
|
|
6
|
+
# Clears out the existing reference documentation.
|
|
7
|
+
class Clobber < SleepingKingStudios::Docs::Jekyll::Commands::Reference
|
|
8
|
+
full_name 'docs:jekyll:clobber'
|
|
9
|
+
|
|
10
|
+
description \
|
|
11
|
+
'Removes any existing reference documentation for the current version'
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
attr_reader :errors
|
|
16
|
+
|
|
17
|
+
def aggregate_errors
|
|
18
|
+
result = yield
|
|
19
|
+
|
|
20
|
+
errors << result.error if result.failure?
|
|
21
|
+
|
|
22
|
+
result
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def process
|
|
26
|
+
@errors = []
|
|
27
|
+
|
|
28
|
+
remove_reference_files
|
|
29
|
+
|
|
30
|
+
remove_data_files(class_data_directory, as: 'class')
|
|
31
|
+
remove_data_files(constant_data_directory, as: 'constant')
|
|
32
|
+
remove_data_files(method_data_directory, as: 'method')
|
|
33
|
+
remove_data_files(module_data_directory, as: 'module')
|
|
34
|
+
remove_data_files(namespace_data_directory, as: 'namespace')
|
|
35
|
+
|
|
36
|
+
report_errors
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def remove_data_files(directory, as:) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
40
|
+
data_count = each_data_file(directory).count
|
|
41
|
+
|
|
42
|
+
say "Removing #{data_count} #{as} objects from #{directory}..."
|
|
43
|
+
say("\n", verbose: true) unless data_count.zero?
|
|
44
|
+
|
|
45
|
+
each_data_file(directory) do |path|
|
|
46
|
+
aggregate_errors { delete_file(path) }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
each_data_directory(directory) do |path|
|
|
50
|
+
aggregate_errors { delete_directory(path, recursive: true) }
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
if version && file_system.directory?(directory)
|
|
54
|
+
aggregate_errors { delete_directory(directory) }
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
say("\n", verbose: true)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def remove_reference_files
|
|
61
|
+
reference_count = each_reference_file.count
|
|
62
|
+
|
|
63
|
+
say "Removing #{reference_count} files from #{reference_directory}..."
|
|
64
|
+
say("\n", verbose: true) unless reference_count.zero?
|
|
65
|
+
|
|
66
|
+
each_reference_file do |path|
|
|
67
|
+
aggregate_errors { delete_file(path) }
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
each_reference_directory do |path|
|
|
71
|
+
aggregate_errors { delete_directory(path, recursive: true) }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
say("\n", verbose: true)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def report_errors # rubocop:disable Metrics/MethodLength
|
|
78
|
+
if errors.empty?
|
|
79
|
+
say 'Success!'
|
|
80
|
+
|
|
81
|
+
return
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
warn 'Failures:'
|
|
85
|
+
warn "\n"
|
|
86
|
+
|
|
87
|
+
errors.each do |error|
|
|
88
|
+
warn " - Unable to remove #{error.path} - #{error.message}"
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
warn "\n"
|
|
92
|
+
|
|
93
|
+
message = 'unable to remove documentation files'
|
|
94
|
+
error = Cuprum::Errors::MultipleErrors.new(errors:, message:)
|
|
95
|
+
|
|
96
|
+
failure(error)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -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
|