docyard 1.0.2 → 1.1.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 +27 -1
- data/lib/docyard/build/asset_bundler.rb +7 -33
- data/lib/docyard/build/file_copier.rb +7 -15
- data/lib/docyard/build/llms_txt_generator.rb +0 -2
- data/lib/docyard/build/sitemap_generator.rb +1 -1
- data/lib/docyard/build/static_generator.rb +30 -32
- data/lib/docyard/build/step_runner.rb +88 -0
- data/lib/docyard/build/validator.rb +98 -0
- data/lib/docyard/builder.rb +82 -55
- data/lib/docyard/cli.rb +36 -4
- data/lib/docyard/components/aliases.rb +0 -4
- data/lib/docyard/components/processors/callout_processor.rb +1 -1
- data/lib/docyard/components/processors/code_block_diff_preprocessor.rb +1 -1
- data/lib/docyard/components/processors/code_block_focus_preprocessor.rb +1 -1
- data/lib/docyard/components/processors/code_block_options_preprocessor.rb +2 -2
- data/lib/docyard/components/processors/code_group_processor.rb +1 -1
- data/lib/docyard/components/processors/icon_processor.rb +2 -2
- data/lib/docyard/components/processors/tabs_processor.rb +1 -1
- data/lib/docyard/config/schema/definition.rb +29 -0
- data/lib/docyard/config/schema/sections.rb +63 -0
- data/lib/docyard/config/schema/simple_sections.rb +78 -0
- data/lib/docyard/config/schema.rb +28 -31
- data/lib/docyard/config/type_validators.rb +121 -0
- data/lib/docyard/config/validator.rb +136 -61
- data/lib/docyard/config.rb +1 -13
- data/lib/docyard/diagnostic.rb +89 -0
- data/lib/docyard/diagnostic_context.rb +48 -0
- data/lib/docyard/doctor/code_block_checker.rb +136 -0
- data/lib/docyard/doctor/component_checker.rb +49 -0
- data/lib/docyard/doctor/component_checkers/abbreviation_checker.rb +74 -0
- data/lib/docyard/doctor/component_checkers/badge_checker.rb +71 -0
- data/lib/docyard/doctor/component_checkers/base.rb +111 -0
- data/lib/docyard/doctor/component_checkers/callout_checker.rb +34 -0
- data/lib/docyard/doctor/component_checkers/cards_checker.rb +57 -0
- data/lib/docyard/doctor/component_checkers/code_group_checker.rb +47 -0
- data/lib/docyard/doctor/component_checkers/details_checker.rb +51 -0
- data/lib/docyard/doctor/component_checkers/icon_checker.rb +36 -0
- data/lib/docyard/doctor/component_checkers/image_attrs_checker.rb +46 -0
- data/lib/docyard/doctor/component_checkers/space_after_colons_checker.rb +45 -0
- data/lib/docyard/doctor/component_checkers/steps_checker.rb +35 -0
- data/lib/docyard/doctor/component_checkers/tabs_checker.rb +35 -0
- data/lib/docyard/doctor/component_checkers/tooltip_checker.rb +67 -0
- data/lib/docyard/doctor/component_checkers/unknown_type_checker.rb +34 -0
- data/lib/docyard/doctor/config_checker.rb +19 -0
- data/lib/docyard/doctor/config_fixer.rb +87 -0
- data/lib/docyard/doctor/content_checker.rb +164 -0
- data/lib/docyard/doctor/file_scanner.rb +113 -0
- data/lib/docyard/doctor/image_checker.rb +103 -0
- data/lib/docyard/doctor/link_checker.rb +91 -0
- data/lib/docyard/doctor/markdown_fixer.rb +62 -0
- data/lib/docyard/doctor/orphan_checker.rb +82 -0
- data/lib/docyard/doctor/reporter.rb +152 -0
- data/lib/docyard/doctor/sidebar_checker.rb +127 -0
- data/lib/docyard/doctor/sidebar_fixer.rb +47 -0
- data/lib/docyard/doctor.rb +178 -0
- data/lib/docyard/editor_launcher.rb +119 -0
- data/lib/docyard/errors.rb +0 -49
- data/lib/docyard/initializer.rb +32 -39
- data/lib/docyard/navigation/sidebar/local_config_loader.rb +44 -21
- data/lib/docyard/rendering/icon_helpers.rb +1 -3
- data/lib/docyard/search/build_indexer.rb +39 -24
- data/lib/docyard/search/dev_indexer.rb +9 -23
- data/lib/docyard/server/dev_server.rb +55 -13
- data/lib/docyard/server/error_overlay.rb +73 -0
- data/lib/docyard/server/file_watcher.rb +0 -1
- data/lib/docyard/server/page_diagnostics.rb +27 -0
- data/lib/docyard/server/preview_server.rb +17 -13
- data/lib/docyard/server/rack_application.rb +64 -3
- data/lib/docyard/server/resolution_result.rb +0 -4
- data/lib/docyard/templates/assets/css/error-overlay.css +669 -0
- data/lib/docyard/templates/assets/css/variables.css +1 -1
- data/lib/docyard/templates/assets/fonts/Inter-Variable.woff2 +0 -0
- data/lib/docyard/templates/assets/js/components/relative-time.js +42 -0
- data/lib/docyard/templates/assets/js/error-overlay.js +547 -0
- data/lib/docyard/templates/assets/js/hot-reload.js +35 -7
- data/lib/docyard/templates/errors/404.html.erb +1 -1
- data/lib/docyard/templates/errors/500.html.erb +1 -1
- data/lib/docyard/templates/partials/_head.html.erb +1 -1
- data/lib/docyard/templates/partials/_page_actions.html.erb +1 -1
- data/lib/docyard/ui.rb +80 -0
- data/lib/docyard/utils/logging.rb +5 -1
- data/lib/docyard/utils/text_formatter.rb +0 -6
- data/lib/docyard/version.rb +1 -1
- data/lib/docyard.rb +4 -0
- metadata +47 -25
- data/lib/docyard/config/key_validator.rb +0 -30
- data/lib/docyard/config/validation_helpers.rb +0 -83
- data/lib/docyard/config/validators/navigation.rb +0 -43
- data/lib/docyard/config/validators/section.rb +0 -114
- data/lib/docyard/templates/assets/fonts/Inter-Variable.ttf +0 -0
data/lib/docyard/ui.rb
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Docyard
|
|
4
|
+
module UI
|
|
5
|
+
CODES = {
|
|
6
|
+
red: 31,
|
|
7
|
+
green: 32,
|
|
8
|
+
yellow: 33,
|
|
9
|
+
cyan: 36,
|
|
10
|
+
bold: 1,
|
|
11
|
+
dim: 2
|
|
12
|
+
}.freeze
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
attr_writer :enabled
|
|
16
|
+
|
|
17
|
+
def enabled?
|
|
18
|
+
return @enabled unless @enabled.nil?
|
|
19
|
+
|
|
20
|
+
@enabled = determine_color_support
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def reset!
|
|
24
|
+
@enabled = nil
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def red(text)
|
|
28
|
+
wrap(text, CODES[:red])
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def green(text)
|
|
32
|
+
wrap(text, CODES[:green])
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def yellow(text)
|
|
36
|
+
wrap(text, CODES[:yellow])
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def cyan(text)
|
|
40
|
+
wrap(text, CODES[:cyan])
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def bold(text)
|
|
44
|
+
wrap(text, CODES[:bold])
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def dim(text)
|
|
48
|
+
wrap(text, CODES[:dim])
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def success(text)
|
|
52
|
+
wrap(text, CODES[:green], CODES[:bold])
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def error(text)
|
|
56
|
+
wrap(text, CODES[:red], CODES[:bold])
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def warning(text)
|
|
60
|
+
wrap(text, CODES[:yellow])
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
def wrap(text, *codes)
|
|
66
|
+
return text.to_s unless enabled?
|
|
67
|
+
|
|
68
|
+
prefix = codes.map { |c| "\e[#{c}m" }.join
|
|
69
|
+
"#{prefix}#{text}\e[0m"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def determine_color_support # rubocop:disable Naming/PredicateMethod
|
|
73
|
+
return false if ENV.key?("NO_COLOR")
|
|
74
|
+
return false unless $stdout.tty?
|
|
75
|
+
|
|
76
|
+
true
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -64,9 +64,13 @@ module Docyard
|
|
|
64
64
|
def format_message(severity, msg)
|
|
65
65
|
case severity
|
|
66
66
|
when "DEBUG"
|
|
67
|
-
"[DEBUG] #{msg}\n"
|
|
67
|
+
"#{UI.dim('[DEBUG]')} #{msg}\n"
|
|
68
68
|
when "INFO"
|
|
69
69
|
"#{msg}\n"
|
|
70
|
+
when "WARN"
|
|
71
|
+
"#{UI.warning('[WARN]')} #{msg}\n"
|
|
72
|
+
when "ERROR"
|
|
73
|
+
"#{UI.error('[ERROR]')} #{msg}\n"
|
|
70
74
|
else
|
|
71
75
|
"[#{severity}] #{msg}\n"
|
|
72
76
|
end
|
data/lib/docyard/version.rb
CHANGED
data/lib/docyard.rb
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
require_relative "docyard/version"
|
|
4
4
|
require_relative "docyard/constants"
|
|
5
5
|
require_relative "docyard/errors"
|
|
6
|
+
require_relative "docyard/diagnostic"
|
|
7
|
+
require_relative "docyard/ui"
|
|
6
8
|
require_relative "docyard/utils/logging"
|
|
7
9
|
|
|
8
10
|
require_relative "docyard/utils/text_formatter"
|
|
@@ -37,5 +39,7 @@ require_relative "docyard/build/asset_bundler"
|
|
|
37
39
|
require_relative "docyard/build/file_copier"
|
|
38
40
|
require_relative "docyard/build/sitemap_generator"
|
|
39
41
|
|
|
42
|
+
require_relative "docyard/doctor"
|
|
43
|
+
|
|
40
44
|
module Docyard
|
|
41
45
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: docyard
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sanif Himani
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: cssminify
|
|
@@ -164,20 +163,6 @@ dependencies:
|
|
|
164
163
|
- - "~>"
|
|
165
164
|
- !ruby/object:Gem::Version
|
|
166
165
|
version: '1.4'
|
|
167
|
-
- !ruby/object:Gem::Dependency
|
|
168
|
-
name: tty-progressbar
|
|
169
|
-
requirement: !ruby/object:Gem::Requirement
|
|
170
|
-
requirements:
|
|
171
|
-
- - "~>"
|
|
172
|
-
- !ruby/object:Gem::Version
|
|
173
|
-
version: '0.18'
|
|
174
|
-
type: :runtime
|
|
175
|
-
prerelease: false
|
|
176
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
177
|
-
requirements:
|
|
178
|
-
- - "~>"
|
|
179
|
-
- !ruby/object:Gem::Version
|
|
180
|
-
version: '0.18'
|
|
181
166
|
description: Generate beautiful documentation sites from Markdown
|
|
182
167
|
email:
|
|
183
168
|
- sanifhimani92@gmail.com
|
|
@@ -199,6 +184,8 @@ files:
|
|
|
199
184
|
- lib/docyard/build/root_fallback_generator.rb
|
|
200
185
|
- lib/docyard/build/sitemap_generator.rb
|
|
201
186
|
- lib/docyard/build/static_generator.rb
|
|
187
|
+
- lib/docyard/build/step_runner.rb
|
|
188
|
+
- lib/docyard/build/validator.rb
|
|
202
189
|
- lib/docyard/builder.rb
|
|
203
190
|
- lib/docyard/cli.rb
|
|
204
191
|
- lib/docyard/components/aliases.rb
|
|
@@ -244,15 +231,46 @@ files:
|
|
|
244
231
|
- lib/docyard/config.rb
|
|
245
232
|
- lib/docyard/config/analytics_resolver.rb
|
|
246
233
|
- lib/docyard/config/branding_resolver.rb
|
|
247
|
-
- lib/docyard/config/key_validator.rb
|
|
248
234
|
- lib/docyard/config/logo_detector.rb
|
|
249
235
|
- lib/docyard/config/schema.rb
|
|
236
|
+
- lib/docyard/config/schema/definition.rb
|
|
237
|
+
- lib/docyard/config/schema/sections.rb
|
|
238
|
+
- lib/docyard/config/schema/simple_sections.rb
|
|
250
239
|
- lib/docyard/config/section.rb
|
|
251
|
-
- lib/docyard/config/
|
|
240
|
+
- lib/docyard/config/type_validators.rb
|
|
252
241
|
- lib/docyard/config/validator.rb
|
|
253
|
-
- lib/docyard/config/validators/navigation.rb
|
|
254
|
-
- lib/docyard/config/validators/section.rb
|
|
255
242
|
- lib/docyard/constants.rb
|
|
243
|
+
- lib/docyard/diagnostic.rb
|
|
244
|
+
- lib/docyard/diagnostic_context.rb
|
|
245
|
+
- lib/docyard/doctor.rb
|
|
246
|
+
- lib/docyard/doctor/code_block_checker.rb
|
|
247
|
+
- lib/docyard/doctor/component_checker.rb
|
|
248
|
+
- lib/docyard/doctor/component_checkers/abbreviation_checker.rb
|
|
249
|
+
- lib/docyard/doctor/component_checkers/badge_checker.rb
|
|
250
|
+
- lib/docyard/doctor/component_checkers/base.rb
|
|
251
|
+
- lib/docyard/doctor/component_checkers/callout_checker.rb
|
|
252
|
+
- lib/docyard/doctor/component_checkers/cards_checker.rb
|
|
253
|
+
- lib/docyard/doctor/component_checkers/code_group_checker.rb
|
|
254
|
+
- lib/docyard/doctor/component_checkers/details_checker.rb
|
|
255
|
+
- lib/docyard/doctor/component_checkers/icon_checker.rb
|
|
256
|
+
- lib/docyard/doctor/component_checkers/image_attrs_checker.rb
|
|
257
|
+
- lib/docyard/doctor/component_checkers/space_after_colons_checker.rb
|
|
258
|
+
- lib/docyard/doctor/component_checkers/steps_checker.rb
|
|
259
|
+
- lib/docyard/doctor/component_checkers/tabs_checker.rb
|
|
260
|
+
- lib/docyard/doctor/component_checkers/tooltip_checker.rb
|
|
261
|
+
- lib/docyard/doctor/component_checkers/unknown_type_checker.rb
|
|
262
|
+
- lib/docyard/doctor/config_checker.rb
|
|
263
|
+
- lib/docyard/doctor/config_fixer.rb
|
|
264
|
+
- lib/docyard/doctor/content_checker.rb
|
|
265
|
+
- lib/docyard/doctor/file_scanner.rb
|
|
266
|
+
- lib/docyard/doctor/image_checker.rb
|
|
267
|
+
- lib/docyard/doctor/link_checker.rb
|
|
268
|
+
- lib/docyard/doctor/markdown_fixer.rb
|
|
269
|
+
- lib/docyard/doctor/orphan_checker.rb
|
|
270
|
+
- lib/docyard/doctor/reporter.rb
|
|
271
|
+
- lib/docyard/doctor/sidebar_checker.rb
|
|
272
|
+
- lib/docyard/doctor/sidebar_fixer.rb
|
|
273
|
+
- lib/docyard/editor_launcher.rb
|
|
256
274
|
- lib/docyard/errors.rb
|
|
257
275
|
- lib/docyard/initializer.rb
|
|
258
276
|
- lib/docyard/navigation/breadcrumb_builder.rb
|
|
@@ -281,7 +299,9 @@ files:
|
|
|
281
299
|
- lib/docyard/search/pagefind_support.rb
|
|
282
300
|
- lib/docyard/server/asset_handler.rb
|
|
283
301
|
- lib/docyard/server/dev_server.rb
|
|
302
|
+
- lib/docyard/server/error_overlay.rb
|
|
284
303
|
- lib/docyard/server/file_watcher.rb
|
|
304
|
+
- lib/docyard/server/page_diagnostics.rb
|
|
285
305
|
- lib/docyard/server/pagefind_handler.rb
|
|
286
306
|
- lib/docyard/server/preview_server.rb
|
|
287
307
|
- lib/docyard/server/rack_application.rb
|
|
@@ -318,6 +338,7 @@ files:
|
|
|
318
338
|
- lib/docyard/templates/assets/css/components/theme-toggle.css
|
|
319
339
|
- lib/docyard/templates/assets/css/components/tooltip.css
|
|
320
340
|
- lib/docyard/templates/assets/css/components/video.css
|
|
341
|
+
- lib/docyard/templates/assets/css/error-overlay.css
|
|
321
342
|
- lib/docyard/templates/assets/css/landing.css
|
|
322
343
|
- lib/docyard/templates/assets/css/layout.css
|
|
323
344
|
- lib/docyard/templates/assets/css/main.css
|
|
@@ -326,7 +347,7 @@ files:
|
|
|
326
347
|
- lib/docyard/templates/assets/css/typography.css
|
|
327
348
|
- lib/docyard/templates/assets/css/variables.css
|
|
328
349
|
- lib/docyard/templates/assets/favicon.svg
|
|
329
|
-
- lib/docyard/templates/assets/fonts/Inter-Variable.
|
|
350
|
+
- lib/docyard/templates/assets/fonts/Inter-Variable.woff2
|
|
330
351
|
- lib/docyard/templates/assets/js/components/abbreviation.js
|
|
331
352
|
- lib/docyard/templates/assets/js/components/banner.js
|
|
332
353
|
- lib/docyard/templates/assets/js/components/code-block.js
|
|
@@ -337,12 +358,14 @@ files:
|
|
|
337
358
|
- lib/docyard/templates/assets/js/components/heading-anchor.js
|
|
338
359
|
- lib/docyard/templates/assets/js/components/lightbox.js
|
|
339
360
|
- lib/docyard/templates/assets/js/components/navigation.js
|
|
361
|
+
- lib/docyard/templates/assets/js/components/relative-time.js
|
|
340
362
|
- lib/docyard/templates/assets/js/components/search.js
|
|
341
363
|
- lib/docyard/templates/assets/js/components/sidebar-toggle.js
|
|
342
364
|
- lib/docyard/templates/assets/js/components/tab-navigation.js
|
|
343
365
|
- lib/docyard/templates/assets/js/components/table-of-contents.js
|
|
344
366
|
- lib/docyard/templates/assets/js/components/tabs.js
|
|
345
367
|
- lib/docyard/templates/assets/js/components/tooltip.js
|
|
368
|
+
- lib/docyard/templates/assets/js/error-overlay.js
|
|
346
369
|
- lib/docyard/templates/assets/js/hot-reload.js
|
|
347
370
|
- lib/docyard/templates/assets/js/theme.js
|
|
348
371
|
- lib/docyard/templates/assets/logo-dark.svg
|
|
@@ -394,6 +417,7 @@ files:
|
|
|
394
417
|
- lib/docyard/templates/partials/_table_of_contents_toggle.html.erb
|
|
395
418
|
- lib/docyard/templates/partials/_tabs.html.erb
|
|
396
419
|
- lib/docyard/templates/partials/_theme_toggle.html.erb
|
|
420
|
+
- lib/docyard/ui.rb
|
|
397
421
|
- lib/docyard/utils/git_info.rb
|
|
398
422
|
- lib/docyard/utils/hash_utils.rb
|
|
399
423
|
- lib/docyard/utils/html_helpers.rb
|
|
@@ -414,7 +438,6 @@ metadata:
|
|
|
414
438
|
documentation_uri: https://docyard.dev
|
|
415
439
|
bug_tracker_uri: https://github.com/sanifhimani/docyard/issues
|
|
416
440
|
rubygems_mfa_required: 'true'
|
|
417
|
-
post_install_message:
|
|
418
441
|
rdoc_options: []
|
|
419
442
|
require_paths:
|
|
420
443
|
- lib
|
|
@@ -429,8 +452,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
429
452
|
- !ruby/object:Gem::Version
|
|
430
453
|
version: '0'
|
|
431
454
|
requirements: []
|
|
432
|
-
rubygems_version: 3.
|
|
433
|
-
signing_key:
|
|
455
|
+
rubygems_version: 3.7.2
|
|
434
456
|
specification_version: 4
|
|
435
457
|
summary: Generate beautiful documentation sites from Markdown
|
|
436
458
|
test_files: []
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Docyard
|
|
4
|
-
class Config
|
|
5
|
-
module KeyValidator
|
|
6
|
-
class << self
|
|
7
|
-
def validate(hash, valid_keys, context:)
|
|
8
|
-
return [] unless hash.is_a?(Hash)
|
|
9
|
-
|
|
10
|
-
unknown = hash.keys.map(&:to_s) - valid_keys
|
|
11
|
-
unknown.map { |key| build_error(key, valid_keys, context) }
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
private
|
|
15
|
-
|
|
16
|
-
def build_error(key, valid_keys, context)
|
|
17
|
-
suggestion = find_suggestion(key, valid_keys)
|
|
18
|
-
msg = "unknown key '#{key}'"
|
|
19
|
-
msg += ". Did you mean '#{suggestion}'?" if suggestion
|
|
20
|
-
{ context: context, message: msg }
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def find_suggestion(key, valid_keys)
|
|
24
|
-
checker = DidYouMean::SpellChecker.new(dictionary: valid_keys)
|
|
25
|
-
checker.correct(key).first
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
end
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Docyard
|
|
4
|
-
class Config
|
|
5
|
-
module ValidationHelpers
|
|
6
|
-
private
|
|
7
|
-
|
|
8
|
-
def validate_string(value, field_name)
|
|
9
|
-
return if value.nil? || value.is_a?(String)
|
|
10
|
-
|
|
11
|
-
add_error(field: field_name, error: "must be a string", got: value.class.name, fix: "Change to a string value")
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def validate_boolean(value, field_name)
|
|
15
|
-
return if [true, false].include?(value)
|
|
16
|
-
|
|
17
|
-
add_error(field: field_name, error: "must be true or false", got: value.inspect, fix: "Change to true or false")
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def validate_url(value, field_name)
|
|
21
|
-
return if value.nil? || value.is_a?(String)
|
|
22
|
-
|
|
23
|
-
add_error(field: field_name, error: "must be a URL string", got: value.class.name,
|
|
24
|
-
fix: "Change to a URL string")
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def validate_array(value, field_name)
|
|
28
|
-
return if value.nil? || value.is_a?(Array)
|
|
29
|
-
|
|
30
|
-
add_array_error(field_name)
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def validate_file_path_or_url(value, field_name)
|
|
34
|
-
return if value.nil?
|
|
35
|
-
return add_type_error(field_name, "file path or URL (string)", value.class.name) unless value.is_a?(String)
|
|
36
|
-
return if url?(value)
|
|
37
|
-
|
|
38
|
-
public_dir = File.join(@config["source"] || "docs", "public")
|
|
39
|
-
file_path = File.absolute_path?(value) ? value : File.join(public_dir, value)
|
|
40
|
-
return if File.exist?(file_path)
|
|
41
|
-
|
|
42
|
-
add_error(field: field_name, error: "file not found", got: value,
|
|
43
|
-
fix: "Place the file in #{public_dir}/ directory (e.g., 'logo.svg' for #{public_dir}/logo.svg)")
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def validate_no_slashes(value, field_name)
|
|
47
|
-
return if value.nil? || !value.is_a?(String)
|
|
48
|
-
return unless value.include?("/") || value.include?("\\")
|
|
49
|
-
|
|
50
|
-
add_error(field: field_name, error: "cannot contain slashes", got: value,
|
|
51
|
-
fix: "Use a simple directory name like 'dist' or '_site'")
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def validate_starts_with_slash(value, field_name)
|
|
55
|
-
return if value.nil? || value.start_with?("/")
|
|
56
|
-
|
|
57
|
-
add_error(field: field_name, error: "must start with /", got: value, fix: "Change to '/#{value}'")
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def url?(value)
|
|
61
|
-
value.match?(%r{\Ahttps?://})
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def add_error(error_data)
|
|
65
|
-
@errors << error_data
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def add_type_error(field, expected, got)
|
|
69
|
-
add_error(field: field, error: "must be a #{expected}", got: got, fix: "Change to a #{expected}")
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def add_hash_error(field)
|
|
73
|
-
add_error(field: field, error: "must be a hash", got: @config[field].class.name,
|
|
74
|
-
fix: "Change to a hash with platform names as keys and URLs as values")
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def add_array_error(field)
|
|
78
|
-
value = field.split(".").reduce(@config) { |h, k| h&.[](k) }
|
|
79
|
-
add_error(field: field, error: "must be an array", got: value.class.name, fix: "Change to an array")
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Docyard
|
|
4
|
-
class Config
|
|
5
|
-
module Validators
|
|
6
|
-
module Navigation
|
|
7
|
-
private
|
|
8
|
-
|
|
9
|
-
def validate_navigation_section
|
|
10
|
-
cta = @config.dig("navigation", "cta")
|
|
11
|
-
return if cta.nil?
|
|
12
|
-
return add_array_error("navigation.cta") unless cta.is_a?(Array)
|
|
13
|
-
|
|
14
|
-
validate_cta_max_count(cta)
|
|
15
|
-
validate_cta_items(cta)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def validate_cta_items(cta)
|
|
19
|
-
cta.each_with_index do |item, idx|
|
|
20
|
-
validate_string(item["text"], "navigation.cta[#{idx}].text")
|
|
21
|
-
validate_string(item["href"], "navigation.cta[#{idx}].href")
|
|
22
|
-
validate_cta_variant(item["variant"], idx) if item.key?("variant")
|
|
23
|
-
validate_boolean(item["external"], "navigation.cta[#{idx}].external") if item.key?("external")
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def validate_cta_max_count(cta)
|
|
28
|
-
return if cta.length <= 2
|
|
29
|
-
|
|
30
|
-
add_error(field: "navigation.cta", error: "maximum 2 CTAs allowed",
|
|
31
|
-
got: "#{cta.length} items", fix: "Remove extra CTA items to have at most 2")
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def validate_cta_variant(variant, idx)
|
|
35
|
-
return if variant.nil? || %w[primary secondary].include?(variant)
|
|
36
|
-
|
|
37
|
-
add_error(field: "navigation.cta[#{idx}].variant", error: "must be 'primary' or 'secondary'",
|
|
38
|
-
got: variant, fix: "Change to 'primary' or 'secondary'")
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
end
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Docyard
|
|
4
|
-
class Config
|
|
5
|
-
module Validators
|
|
6
|
-
module Section
|
|
7
|
-
private
|
|
8
|
-
|
|
9
|
-
def validate_top_level
|
|
10
|
-
validate_string(@config["title"], "title")
|
|
11
|
-
validate_string(@config["description"], "description")
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def validate_branding_section
|
|
15
|
-
branding = @config["branding"]
|
|
16
|
-
return unless branding
|
|
17
|
-
|
|
18
|
-
validate_file_path_or_url(branding["logo"], "branding.logo")
|
|
19
|
-
validate_file_path_or_url(branding["favicon"], "branding.favicon")
|
|
20
|
-
validate_boolean(branding["credits"], "branding.credits") if branding.key?("credits")
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def validate_socials_section
|
|
24
|
-
socials = @config["socials"]
|
|
25
|
-
return unless socials
|
|
26
|
-
return add_hash_error("socials") unless socials.is_a?(Hash)
|
|
27
|
-
|
|
28
|
-
socials.each { |platform, url| validate_url(url, "socials.#{platform}") unless platform == "custom" }
|
|
29
|
-
validate_custom_socials(socials["custom"]) if socials.key?("custom")
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def validate_custom_socials(custom)
|
|
33
|
-
return if custom.nil?
|
|
34
|
-
return add_array_error("socials.custom") unless custom.is_a?(Array)
|
|
35
|
-
|
|
36
|
-
custom.each_with_index do |item, index|
|
|
37
|
-
validate_string(item["icon"], "socials.custom[#{index}].icon")
|
|
38
|
-
validate_url(item["href"], "socials.custom[#{index}].href")
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def validate_tabs_section
|
|
43
|
-
tabs = @config["tabs"]
|
|
44
|
-
return unless tabs
|
|
45
|
-
return add_array_error("tabs") unless tabs.is_a?(Array)
|
|
46
|
-
|
|
47
|
-
tabs.each_with_index do |tab, index|
|
|
48
|
-
validate_string(tab["text"], "tabs[#{index}].text")
|
|
49
|
-
validate_string(tab["href"], "tabs[#{index}].href")
|
|
50
|
-
validate_boolean(tab["external"], "tabs[#{index}].external") if tab.key?("external")
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def validate_sidebar_setting
|
|
55
|
-
sidebar = @config["sidebar"]
|
|
56
|
-
return if sidebar.nil? || Config::SIDEBAR_MODES.include?(sidebar)
|
|
57
|
-
|
|
58
|
-
add_error(
|
|
59
|
-
field: "sidebar",
|
|
60
|
-
error: "must be one of: #{Config::SIDEBAR_MODES.join(', ')}",
|
|
61
|
-
got: sidebar.inspect,
|
|
62
|
-
fix: "Change to 'config', 'auto', or 'distributed'"
|
|
63
|
-
)
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def validate_build_section
|
|
67
|
-
build = @config["build"]
|
|
68
|
-
return unless build
|
|
69
|
-
|
|
70
|
-
validate_string(build["output"], "build.output")
|
|
71
|
-
validate_no_slashes(build["output"], "build.output")
|
|
72
|
-
validate_string(build["base"], "build.base")
|
|
73
|
-
validate_starts_with_slash(build["base"], "build.base")
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def validate_search_section
|
|
77
|
-
search = @config["search"]
|
|
78
|
-
return unless search
|
|
79
|
-
|
|
80
|
-
validate_boolean(search["enabled"], "search.enabled") if search.key?("enabled")
|
|
81
|
-
validate_string(search["placeholder"], "search.placeholder") if search.key?("placeholder")
|
|
82
|
-
validate_array(search["exclude"], "search.exclude") if search.key?("exclude")
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
def validate_announcement_section
|
|
86
|
-
announcement = @config["announcement"]
|
|
87
|
-
return unless announcement.is_a?(Hash)
|
|
88
|
-
|
|
89
|
-
validate_string(announcement["text"], "announcement.text") if announcement.key?("text")
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
def validate_feedback_section
|
|
93
|
-
feedback = @config["feedback"]
|
|
94
|
-
return unless feedback.is_a?(Hash) && feedback["enabled"] == true
|
|
95
|
-
return if analytics_configured?
|
|
96
|
-
|
|
97
|
-
add_error(
|
|
98
|
-
field: "feedback.enabled",
|
|
99
|
-
error: "requires analytics to be configured",
|
|
100
|
-
got: "feedback enabled without analytics",
|
|
101
|
-
fix: "Configure analytics (google, plausible, fathom, or script) to collect feedback responses"
|
|
102
|
-
)
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def analytics_configured?
|
|
106
|
-
analytics = @config["analytics"]
|
|
107
|
-
return false unless analytics.is_a?(Hash)
|
|
108
|
-
|
|
109
|
-
analytics["google"] || analytics["plausible"] || analytics["fathom"] || analytics["script"]
|
|
110
|
-
end
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
end
|
|
Binary file
|