docyard 0.9.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +43 -0
- data/README.md +8 -253
- data/exe/docyard +6 -0
- data/lib/docyard/build/asset_bundler.rb +2 -2
- data/lib/docyard/build/file_copier.rb +12 -5
- data/lib/docyard/build/llms_txt_generator.rb +103 -0
- data/lib/docyard/build/sitemap_generator.rb +1 -1
- data/lib/docyard/build/static_generator.rb +115 -79
- data/lib/docyard/builder.rb +6 -2
- data/lib/docyard/cli.rb +14 -4
- data/lib/docyard/components/processors/callout_processor.rb +1 -1
- data/lib/docyard/components/processors/code_block_extended_fence_postprocessor.rb +24 -0
- data/lib/docyard/components/processors/code_block_extended_fence_preprocessor.rb +44 -0
- data/lib/docyard/components/processors/code_block_options_preprocessor.rb +11 -1
- data/lib/docyard/components/processors/code_block_processor.rb +5 -24
- data/lib/docyard/components/processors/code_group_processor.rb +6 -22
- data/lib/docyard/components/processors/code_snippet_import_preprocessor.rb +1 -0
- data/lib/docyard/components/processors/file_tree_processor.rb +1 -2
- data/lib/docyard/components/processors/icon_processor.rb +8 -2
- data/lib/docyard/components/processors/include_processor.rb +10 -10
- data/lib/docyard/components/processors/video_embed_processor.rb +14 -3
- data/lib/docyard/components/support/code_block/feature_extractor.rb +3 -1
- data/lib/docyard/components/support/code_block/icon_detector.rb +5 -12
- data/lib/docyard/components/support/code_block/line_number_resolver.rb +30 -0
- data/lib/docyard/components/support/code_detector.rb +2 -12
- data/lib/docyard/components/support/code_group/html_builder.rb +2 -6
- data/lib/docyard/components/support/tabs/icon_detector.rb +6 -2
- data/lib/docyard/components/support/tabs/parser.rb +6 -23
- data/lib/docyard/config/analytics_resolver.rb +24 -0
- data/lib/docyard/config/branding_resolver.rb +58 -27
- data/lib/docyard/config/key_validator.rb +30 -0
- data/lib/docyard/config/logo_detector.rb +8 -8
- data/lib/docyard/config/schema.rb +39 -0
- data/lib/docyard/config/section.rb +21 -0
- data/lib/docyard/config/validation_helpers.rb +83 -0
- data/lib/docyard/config/validator.rb +45 -144
- data/lib/docyard/config/validators/navigation.rb +43 -0
- data/lib/docyard/config/validators/section.rb +114 -0
- data/lib/docyard/config.rb +46 -102
- data/lib/docyard/constants.rb +59 -0
- data/lib/docyard/{utils/errors.rb → errors.rb} +6 -0
- data/lib/docyard/initializer.rb +100 -49
- data/lib/docyard/navigation/page_navigation_builder.rb +65 -0
- data/lib/docyard/navigation/sidebar/auto_builder.rb +107 -0
- data/lib/docyard/navigation/sidebar/cache.rb +96 -0
- data/lib/docyard/navigation/sidebar/config_builder.rb +179 -0
- data/lib/docyard/navigation/sidebar/distributed_builder.rb +145 -0
- data/lib/docyard/navigation/sidebar/local_config_loader.rb +69 -3
- data/lib/docyard/navigation/sidebar/renderer.rb +12 -1
- data/lib/docyard/navigation/sidebar_builder.rb +43 -81
- data/lib/docyard/rendering/branding_variables.rb +65 -0
- data/lib/docyard/rendering/icon_helpers.rb +14 -1
- data/lib/docyard/rendering/icons/devicons.rb +63 -0
- data/lib/docyard/rendering/icons.rb +26 -27
- data/lib/docyard/rendering/markdown.rb +5 -23
- data/lib/docyard/rendering/og_helpers.rb +36 -0
- data/lib/docyard/rendering/renderer.rb +87 -59
- data/lib/docyard/rendering/template_resolver.rb +14 -0
- data/lib/docyard/routing/fallback_resolver.rb +3 -3
- data/lib/docyard/search/build_indexer.rb +2 -2
- data/lib/docyard/search/dev_indexer.rb +36 -28
- data/lib/docyard/search/pagefind_support.rb +1 -1
- data/lib/docyard/server/asset_handler.rb +39 -15
- data/lib/docyard/server/dev_server.rb +90 -55
- data/lib/docyard/server/file_watcher.rb +68 -18
- data/lib/docyard/server/pagefind_handler.rb +1 -1
- data/lib/docyard/server/preview_server.rb +29 -33
- data/lib/docyard/server/rack_application.rb +38 -70
- data/lib/docyard/server/router.rb +11 -7
- data/lib/docyard/server/sse_server.rb +157 -0
- data/lib/docyard/server/static_file_app.rb +42 -0
- data/lib/docyard/templates/assets/css/components/banner.css +31 -0
- data/lib/docyard/templates/assets/css/components/breadcrumbs.css +2 -1
- data/lib/docyard/templates/assets/css/components/callout.css +26 -6
- data/lib/docyard/templates/assets/css/components/code-block.css +4 -2
- data/lib/docyard/templates/assets/css/components/code-group.css +20 -7
- data/lib/docyard/templates/assets/css/components/feedback.css +126 -0
- data/lib/docyard/templates/assets/css/components/file-tree.css +5 -4
- data/lib/docyard/templates/assets/css/components/icon.css +5 -0
- data/lib/docyard/templates/assets/css/components/nav-menu.css +20 -4
- data/lib/docyard/templates/assets/css/components/navigation.css +25 -3
- data/lib/docyard/templates/assets/css/components/page-actions.css +131 -0
- data/lib/docyard/templates/assets/css/components/prev-next.css +14 -7
- data/lib/docyard/templates/assets/css/components/search.css +6 -10
- data/lib/docyard/templates/assets/css/components/tab-bar.css +7 -4
- data/lib/docyard/templates/assets/css/components/table-of-contents.css +57 -11
- data/lib/docyard/templates/assets/css/components/tabs.css +12 -4
- data/lib/docyard/templates/assets/css/components/theme-toggle.css +3 -1
- data/lib/docyard/templates/assets/css/landing.css +82 -13
- data/lib/docyard/templates/assets/css/layout.css +17 -0
- data/lib/docyard/templates/assets/css/markdown.css +22 -2
- data/lib/docyard/templates/assets/css/variables.css +13 -1
- data/lib/docyard/templates/assets/js/components/code-group.js +4 -1
- data/lib/docyard/templates/assets/js/components/copy-page.js +115 -0
- data/lib/docyard/templates/assets/js/components/feedback.js +66 -0
- data/lib/docyard/templates/assets/js/components/file-tree.js +5 -5
- data/lib/docyard/templates/assets/js/components/navigation.js +3 -3
- data/lib/docyard/templates/assets/js/components/search.js +3 -3
- data/lib/docyard/templates/assets/js/components/table-of-contents.js +12 -6
- data/lib/docyard/templates/assets/js/components/tabs.js +45 -22
- data/lib/docyard/templates/assets/js/components/tooltip.js +4 -4
- data/lib/docyard/templates/assets/js/hot-reload.js +44 -0
- data/lib/docyard/templates/errors/404.html.erb +114 -5
- data/lib/docyard/templates/errors/500.html.erb +173 -10
- data/lib/docyard/templates/init/_sidebar.yml +36 -0
- data/lib/docyard/templates/init/docyard.yml +36 -0
- data/lib/docyard/templates/init/pages/components.md +146 -0
- data/lib/docyard/templates/init/pages/getting-started.md +94 -0
- data/lib/docyard/templates/init/pages/index.md +22 -0
- data/lib/docyard/templates/layouts/default.html.erb +10 -0
- data/lib/docyard/templates/layouts/splash.html.erb +14 -1
- data/lib/docyard/templates/partials/_analytics.html.erb +24 -0
- data/lib/docyard/templates/partials/_banner.html.erb +1 -1
- data/lib/docyard/templates/partials/_code_block.html.erb +1 -1
- data/lib/docyard/templates/partials/_feedback.html.erb +14 -0
- data/lib/docyard/templates/partials/_footer.html.erb +1 -1
- data/lib/docyard/templates/partials/_head.html.erb +79 -4
- data/lib/docyard/templates/partials/_icon_library.html.erb +8 -0
- data/lib/docyard/templates/partials/_page_actions.html.erb +21 -0
- data/lib/docyard/templates/partials/_scripts.html.erb +6 -3
- data/lib/docyard/templates/partials/_tabs.html.erb +4 -1
- data/lib/docyard/utils/git_info.rb +157 -0
- data/lib/docyard/utils/hash_utils.rb +31 -0
- data/lib/docyard/utils/html_helpers.rb +8 -0
- data/lib/docyard/utils/logging.rb +44 -3
- data/lib/docyard/utils/path_resolver.rb +0 -10
- data/lib/docyard/utils/path_utils.rb +73 -0
- data/lib/docyard/version.rb +1 -1
- data/lib/docyard.rb +2 -2
- metadata +77 -47
- data/.github/ISSUE_TEMPLATE/bug_report.md +0 -31
- data/.github/ISSUE_TEMPLATE/feature_request.md +0 -19
- data/.github/pull_request_template.md +0 -14
- data/.github/workflows/ci.yml +0 -49
- data/.rubocop.yml +0 -42
- data/CODE_OF_CONDUCT.md +0 -132
- data/CONTRIBUTING.md +0 -55
- data/LICENSE.vscode-icons +0 -42
- data/Rakefile +0 -8
- data/lib/docyard/config/constants.rb +0 -31
- data/lib/docyard/navigation/sidebar/children_discoverer.rb +0 -51
- data/lib/docyard/navigation/sidebar/config_parser.rb +0 -208
- data/lib/docyard/navigation/sidebar/file_resolver.rb +0 -90
- data/lib/docyard/navigation/sidebar/file_system_scanner.rb +0 -78
- data/lib/docyard/navigation/sidebar/metadata_extractor.rb +0 -71
- data/lib/docyard/navigation/sidebar/metadata_reader.rb +0 -51
- data/lib/docyard/navigation/sidebar/path_prefixer.rb +0 -34
- data/lib/docyard/navigation/sidebar/sorter.rb +0 -21
- data/lib/docyard/navigation/sidebar/title_extractor.rb +0 -25
- data/lib/docyard/navigation/sidebar/tree_builder.rb +0 -140
- data/lib/docyard/rendering/icons/LICENSE.phosphor +0 -21
- data/lib/docyard/rendering/icons/file_types.rb +0 -79
- data/lib/docyard/rendering/icons/phosphor.rb +0 -93
- data/lib/docyard/rendering/language_mapping.rb +0 -52
- data/lib/docyard/templates/assets/js/reload.js +0 -98
- data/lib/docyard/templates/partials/_icon.html.erb +0 -1
- data/lib/docyard/templates/partials/_icon_file_extension.html.erb +0 -1
- data/sig/docyard.rbs +0 -4
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "open3"
|
|
4
|
+
|
|
5
|
+
module Docyard
|
|
6
|
+
module Utils
|
|
7
|
+
class GitInfo
|
|
8
|
+
TIME_UNITS = [
|
|
9
|
+
[60, "minute"],
|
|
10
|
+
[3600, "hour"],
|
|
11
|
+
[86_400, "day"],
|
|
12
|
+
[604_800, "week"],
|
|
13
|
+
[2_592_000, "month"],
|
|
14
|
+
[31_536_000, "year"]
|
|
15
|
+
].freeze
|
|
16
|
+
|
|
17
|
+
class << self
|
|
18
|
+
attr_accessor :timestamp_cache
|
|
19
|
+
|
|
20
|
+
def prefetch_timestamps(docs_path = "docs")
|
|
21
|
+
return unless git_repository?
|
|
22
|
+
|
|
23
|
+
@timestamp_cache = fetch_all_timestamps(docs_path)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def clear_cache
|
|
27
|
+
@timestamp_cache = nil
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def cached_timestamp(file_path)
|
|
31
|
+
return nil unless @timestamp_cache
|
|
32
|
+
|
|
33
|
+
@timestamp_cache[file_path]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def git_repository?
|
|
37
|
+
File.directory?(".git") || system("git", "rev-parse", "--git-dir", out: File::NULL, err: File::NULL)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def fetch_all_timestamps(docs_path)
|
|
43
|
+
output, _, status = Open3.capture3("git", "log", "--pretty=format:%cI", "--name-only", "--", "#{docs_path}/")
|
|
44
|
+
return {} unless status.success?
|
|
45
|
+
|
|
46
|
+
parse_git_log_output(output)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def parse_git_log_output(output)
|
|
50
|
+
timestamps = {}
|
|
51
|
+
current_timestamp = nil
|
|
52
|
+
|
|
53
|
+
output.each_line do |line|
|
|
54
|
+
line = line.strip
|
|
55
|
+
next if line.empty?
|
|
56
|
+
|
|
57
|
+
if line.match?(/^\d{4}-\d{2}-\d{2}T/)
|
|
58
|
+
current_timestamp = Time.parse(line)
|
|
59
|
+
elsif current_timestamp && !timestamps.key?(line)
|
|
60
|
+
timestamps[line] = current_timestamp
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
timestamps
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
attr_reader :repo_url, :branch, :edit_path
|
|
69
|
+
|
|
70
|
+
def initialize(repo_url:, branch: "main", edit_path: "docs")
|
|
71
|
+
@repo_url = repo_url
|
|
72
|
+
@branch = branch
|
|
73
|
+
@edit_path = edit_path
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def edit_url(file_path)
|
|
77
|
+
return nil unless repo_url
|
|
78
|
+
|
|
79
|
+
relative_path = extract_relative_path(file_path)
|
|
80
|
+
return nil unless relative_path
|
|
81
|
+
|
|
82
|
+
normalized_url = repo_url.chomp("/")
|
|
83
|
+
"#{normalized_url}/edit/#{branch}/#{edit_path}/#{relative_path}"
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def last_updated(file_path)
|
|
87
|
+
return nil unless file_path && File.exist?(file_path)
|
|
88
|
+
return nil unless self.class.git_repository?
|
|
89
|
+
|
|
90
|
+
timestamp = git_last_commit_time(file_path)
|
|
91
|
+
return nil unless timestamp
|
|
92
|
+
|
|
93
|
+
{
|
|
94
|
+
time: timestamp,
|
|
95
|
+
iso: timestamp.iso8601,
|
|
96
|
+
formatted: format_datetime(timestamp),
|
|
97
|
+
formatted_short: format_date_short(timestamp),
|
|
98
|
+
relative: relative_time(timestamp)
|
|
99
|
+
}
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
private
|
|
103
|
+
|
|
104
|
+
def extract_relative_path(file_path)
|
|
105
|
+
return nil unless file_path
|
|
106
|
+
|
|
107
|
+
match = file_path.match(%r{#{Regexp.escape(edit_path)}/(.+)$})
|
|
108
|
+
match ? match[1] : nil
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def git_last_commit_time(file_path)
|
|
112
|
+
cached = self.class.cached_timestamp(file_path)
|
|
113
|
+
return cached if cached
|
|
114
|
+
|
|
115
|
+
fetch_single_timestamp(file_path)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def fetch_single_timestamp(file_path)
|
|
119
|
+
output, _, status = Open3.capture3("git", "log", "-1", "--format=%cI", "--", file_path)
|
|
120
|
+
return nil unless status.success?
|
|
121
|
+
return nil if output.strip.empty?
|
|
122
|
+
|
|
123
|
+
Time.parse(output.strip)
|
|
124
|
+
rescue ArgumentError
|
|
125
|
+
nil
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def format_datetime(time)
|
|
129
|
+
time.strftime("%B %-d, %Y at %-I:%M %p")
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def format_date_short(time)
|
|
133
|
+
time.strftime("%b %-d, %Y")
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def relative_time(time)
|
|
137
|
+
seconds = Time.now - time
|
|
138
|
+
return "just now" if seconds < TIME_UNITS.first.first
|
|
139
|
+
|
|
140
|
+
divisor, unit = find_time_unit(seconds)
|
|
141
|
+
pluralize((seconds / divisor).to_i, unit)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def find_time_unit(seconds)
|
|
145
|
+
TIME_UNITS.reverse_each do |threshold, unit|
|
|
146
|
+
return [threshold, unit] if seconds >= threshold
|
|
147
|
+
end
|
|
148
|
+
TIME_UNITS.first
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def pluralize(count, word)
|
|
152
|
+
suffix = count == 1 ? "" : "s"
|
|
153
|
+
"#{count} #{word}#{suffix} ago"
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Docyard
|
|
4
|
+
module Utils
|
|
5
|
+
module HashUtils
|
|
6
|
+
module_function
|
|
7
|
+
|
|
8
|
+
def deep_merge(hash1, hash2)
|
|
9
|
+
hash1.merge(hash2) do |_key, v1, v2|
|
|
10
|
+
if v2.nil?
|
|
11
|
+
v1
|
|
12
|
+
elsif v1.is_a?(Hash) && v2.is_a?(Hash)
|
|
13
|
+
deep_merge(v1, v2)
|
|
14
|
+
else
|
|
15
|
+
v2
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def deep_dup(hash)
|
|
21
|
+
hash.transform_values do |value|
|
|
22
|
+
case value
|
|
23
|
+
when Hash then deep_dup(value)
|
|
24
|
+
when Array then value.map { |v| v.is_a?(Hash) ? deep_dup(v) : v }
|
|
25
|
+
else value
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
module Docyard
|
|
4
4
|
module Utils
|
|
5
5
|
module HtmlHelpers
|
|
6
|
+
def escape_html(text)
|
|
7
|
+
text.to_s
|
|
8
|
+
.gsub("&", "&")
|
|
9
|
+
.gsub("<", "<")
|
|
10
|
+
.gsub(">", ">")
|
|
11
|
+
.gsub('"', """)
|
|
12
|
+
end
|
|
13
|
+
|
|
6
14
|
def escape_html_attribute(text)
|
|
7
15
|
text.gsub('"', """)
|
|
8
16
|
.gsub("'", "'")
|
|
@@ -15,6 +15,32 @@ module Docyard
|
|
|
15
15
|
logger.level = Logger.const_get(level.to_s.upcase)
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
+
def start_buffering
|
|
19
|
+
@buffered_warnings = []
|
|
20
|
+
@buffering = true
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def stop_buffering
|
|
24
|
+
@buffering = false
|
|
25
|
+
warnings = @buffered_warnings || []
|
|
26
|
+
@buffered_warnings = []
|
|
27
|
+
warnings
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def buffering?
|
|
31
|
+
@buffering == true
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def buffer_warning(message)
|
|
35
|
+
@buffered_warnings ||= []
|
|
36
|
+
@buffered_warnings << message
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def flush_warnings
|
|
40
|
+
warnings = stop_buffering
|
|
41
|
+
warnings.each { |msg| logger.warn(msg) }
|
|
42
|
+
end
|
|
43
|
+
|
|
18
44
|
private
|
|
19
45
|
|
|
20
46
|
def default_logger
|
|
@@ -25,9 +51,24 @@ module Docyard
|
|
|
25
51
|
end
|
|
26
52
|
|
|
27
53
|
def log_formatter
|
|
28
|
-
proc do |severity,
|
|
29
|
-
|
|
30
|
-
|
|
54
|
+
proc do |severity, _datetime, _progname, msg|
|
|
55
|
+
if severity == "WARN" && buffering?
|
|
56
|
+
buffer_warning(msg)
|
|
57
|
+
nil
|
|
58
|
+
else
|
|
59
|
+
format_message(severity, msg)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def format_message(severity, msg)
|
|
65
|
+
case severity
|
|
66
|
+
when "DEBUG"
|
|
67
|
+
"[DEBUG] #{msg}\n"
|
|
68
|
+
when "INFO"
|
|
69
|
+
"#{msg}\n"
|
|
70
|
+
else
|
|
71
|
+
"[#{severity}] #{msg}\n"
|
|
31
72
|
end
|
|
32
73
|
end
|
|
33
74
|
end
|
|
@@ -16,16 +16,6 @@ module Docyard
|
|
|
16
16
|
normalized = "/#{normalized}" unless normalized.start_with?("/")
|
|
17
17
|
normalized
|
|
18
18
|
end
|
|
19
|
-
|
|
20
|
-
def self.to_url(relative_path)
|
|
21
|
-
normalize(relative_path)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def self.ancestor?(parent_path, child_path)
|
|
25
|
-
return false if parent_path.nil?
|
|
26
|
-
|
|
27
|
-
child_path.start_with?(parent_path) && child_path != parent_path
|
|
28
|
-
end
|
|
29
19
|
end
|
|
30
20
|
end
|
|
31
21
|
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "uri"
|
|
4
|
+
|
|
5
|
+
module Docyard
|
|
6
|
+
module Utils
|
|
7
|
+
module PathUtils
|
|
8
|
+
module_function
|
|
9
|
+
|
|
10
|
+
def sanitize_url_path(request_path)
|
|
11
|
+
decoded = decode_path(request_path)
|
|
12
|
+
clean = decoded.delete_prefix("/").delete_suffix("/")
|
|
13
|
+
clean = "index" if clean.empty?
|
|
14
|
+
clean.delete_suffix(".md")
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def safe_path?(requested_path, base_dir)
|
|
18
|
+
return false if requested_path.nil? || base_dir.nil?
|
|
19
|
+
|
|
20
|
+
expanded_base = File.expand_path(base_dir)
|
|
21
|
+
expanded_path = File.expand_path(requested_path, base_dir)
|
|
22
|
+
expanded_path.start_with?("#{expanded_base}/") || expanded_path == expanded_base
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def resolve_safe_path(relative_path, base_dir)
|
|
26
|
+
return nil if relative_path.nil? || base_dir.nil?
|
|
27
|
+
|
|
28
|
+
decoded = decode_path(relative_path)
|
|
29
|
+
full_path = File.join(base_dir, decoded)
|
|
30
|
+
expanded = File.expand_path(full_path)
|
|
31
|
+
expanded_base = File.expand_path(base_dir)
|
|
32
|
+
|
|
33
|
+
return nil unless expanded.start_with?("#{expanded_base}/")
|
|
34
|
+
|
|
35
|
+
expanded
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def decode_path(path)
|
|
39
|
+
decoded = URI.decode_www_form_component(path.to_s)
|
|
40
|
+
decoded.gsub(/\\+/, "/")
|
|
41
|
+
rescue ArgumentError
|
|
42
|
+
path.to_s
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def markdown_file_to_url(file_path, docs_path)
|
|
46
|
+
relative_path = file_path.delete_prefix("#{docs_path}/")
|
|
47
|
+
relative_path_to_url(relative_path)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def relative_path_to_url(relative_path)
|
|
51
|
+
base_name = File.basename(relative_path, ".md")
|
|
52
|
+
dir_name = File.dirname(relative_path)
|
|
53
|
+
|
|
54
|
+
if base_name == "index"
|
|
55
|
+
dir_name == "." ? "/" : "/#{dir_name}"
|
|
56
|
+
else
|
|
57
|
+
dir_name == "." ? "/#{base_name}" : "/#{dir_name}/#{base_name}"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def markdown_to_html_output(relative_path, output_dir)
|
|
62
|
+
base_name = File.basename(relative_path, ".md")
|
|
63
|
+
dir_name = File.dirname(relative_path)
|
|
64
|
+
|
|
65
|
+
if base_name == "index"
|
|
66
|
+
File.join(output_dir, dir_name, "index.html")
|
|
67
|
+
else
|
|
68
|
+
File.join(output_dir, dir_name, base_name, "index.html")
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
data/lib/docyard/version.rb
CHANGED
data/lib/docyard.rb
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "docyard/version"
|
|
4
|
-
require_relative "docyard/
|
|
5
|
-
require_relative "docyard/
|
|
4
|
+
require_relative "docyard/constants"
|
|
5
|
+
require_relative "docyard/errors"
|
|
6
6
|
require_relative "docyard/utils/logging"
|
|
7
7
|
|
|
8
8
|
require_relative "docyard/utils/text_formatter"
|
metadata
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: docyard
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 1.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sanif Himani
|
|
8
|
+
autorequire:
|
|
8
9
|
bindir: exe
|
|
9
10
|
cert_chain: []
|
|
10
|
-
date:
|
|
11
|
+
date: 2026-01-22 00:00:00.000000000 Z
|
|
11
12
|
dependencies:
|
|
12
13
|
- !ruby/object:Gem::Dependency
|
|
13
14
|
name: cssminify
|
|
@@ -79,6 +80,34 @@ dependencies:
|
|
|
79
80
|
- - "~>"
|
|
80
81
|
- !ruby/object:Gem::Version
|
|
81
82
|
version: '1.6'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: parallel
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - "~>"
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '1.26'
|
|
90
|
+
type: :runtime
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - "~>"
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '1.26'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: puma
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - "~>"
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '7.0'
|
|
104
|
+
type: :runtime
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - "~>"
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '7.0'
|
|
82
111
|
- !ruby/object:Gem::Dependency
|
|
83
112
|
name: rack
|
|
84
113
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -149,42 +178,22 @@ dependencies:
|
|
|
149
178
|
- - "~>"
|
|
150
179
|
- !ruby/object:Gem::Version
|
|
151
180
|
version: '0.18'
|
|
152
|
-
- !ruby/object:Gem::Dependency
|
|
153
|
-
name: webrick
|
|
154
|
-
requirement: !ruby/object:Gem::Requirement
|
|
155
|
-
requirements:
|
|
156
|
-
- - "~>"
|
|
157
|
-
- !ruby/object:Gem::Version
|
|
158
|
-
version: '1.0'
|
|
159
|
-
type: :runtime
|
|
160
|
-
prerelease: false
|
|
161
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
162
|
-
requirements:
|
|
163
|
-
- - "~>"
|
|
164
|
-
- !ruby/object:Gem::Version
|
|
165
|
-
version: '1.0'
|
|
166
181
|
description: Beautiful, zero-config documentation sites. Built with Ruby.
|
|
167
182
|
email:
|
|
168
183
|
- sanifhimani92@gmail.com
|
|
169
|
-
executables:
|
|
184
|
+
executables:
|
|
185
|
+
- docyard
|
|
170
186
|
extensions: []
|
|
171
187
|
extra_rdoc_files: []
|
|
172
188
|
files:
|
|
173
|
-
- ".github/ISSUE_TEMPLATE/bug_report.md"
|
|
174
|
-
- ".github/ISSUE_TEMPLATE/feature_request.md"
|
|
175
|
-
- ".github/pull_request_template.md"
|
|
176
|
-
- ".github/workflows/ci.yml"
|
|
177
|
-
- ".rubocop.yml"
|
|
178
189
|
- CHANGELOG.md
|
|
179
|
-
- CODE_OF_CONDUCT.md
|
|
180
|
-
- CONTRIBUTING.md
|
|
181
190
|
- LICENSE.txt
|
|
182
|
-
- LICENSE.vscode-icons
|
|
183
191
|
- README.md
|
|
184
|
-
-
|
|
192
|
+
- exe/docyard
|
|
185
193
|
- lib/docyard.rb
|
|
186
194
|
- lib/docyard/build/asset_bundler.rb
|
|
187
195
|
- lib/docyard/build/file_copier.rb
|
|
196
|
+
- lib/docyard/build/llms_txt_generator.rb
|
|
188
197
|
- lib/docyard/build/sitemap_generator.rb
|
|
189
198
|
- lib/docyard/build/static_generator.rb
|
|
190
199
|
- lib/docyard/builder.rb
|
|
@@ -197,6 +206,8 @@ files:
|
|
|
197
206
|
- lib/docyard/components/processors/callout_processor.rb
|
|
198
207
|
- lib/docyard/components/processors/cards_processor.rb
|
|
199
208
|
- lib/docyard/components/processors/code_block_diff_preprocessor.rb
|
|
209
|
+
- lib/docyard/components/processors/code_block_extended_fence_postprocessor.rb
|
|
210
|
+
- lib/docyard/components/processors/code_block_extended_fence_preprocessor.rb
|
|
200
211
|
- lib/docyard/components/processors/code_block_focus_preprocessor.rb
|
|
201
212
|
- lib/docyard/components/processors/code_block_options_preprocessor.rb
|
|
202
213
|
- lib/docyard/components/processors/code_block_processor.rb
|
|
@@ -217,6 +228,7 @@ files:
|
|
|
217
228
|
- lib/docyard/components/registry.rb
|
|
218
229
|
- lib/docyard/components/support/code_block/feature_extractor.rb
|
|
219
230
|
- lib/docyard/components/support/code_block/icon_detector.rb
|
|
231
|
+
- lib/docyard/components/support/code_block/line_number_resolver.rb
|
|
220
232
|
- lib/docyard/components/support/code_block/line_parser.rb
|
|
221
233
|
- lib/docyard/components/support/code_block/line_wrapper.rb
|
|
222
234
|
- lib/docyard/components/support/code_block/patterns.rb
|
|
@@ -227,35 +239,37 @@ files:
|
|
|
227
239
|
- lib/docyard/components/support/tabs/parser.rb
|
|
228
240
|
- lib/docyard/components/support/tabs/range_finder.rb
|
|
229
241
|
- lib/docyard/config.rb
|
|
242
|
+
- lib/docyard/config/analytics_resolver.rb
|
|
230
243
|
- lib/docyard/config/branding_resolver.rb
|
|
231
|
-
- lib/docyard/config/
|
|
244
|
+
- lib/docyard/config/key_validator.rb
|
|
232
245
|
- lib/docyard/config/logo_detector.rb
|
|
246
|
+
- lib/docyard/config/schema.rb
|
|
247
|
+
- lib/docyard/config/section.rb
|
|
248
|
+
- lib/docyard/config/validation_helpers.rb
|
|
233
249
|
- lib/docyard/config/validator.rb
|
|
250
|
+
- lib/docyard/config/validators/navigation.rb
|
|
251
|
+
- lib/docyard/config/validators/section.rb
|
|
252
|
+
- lib/docyard/constants.rb
|
|
253
|
+
- lib/docyard/errors.rb
|
|
234
254
|
- lib/docyard/initializer.rb
|
|
235
255
|
- lib/docyard/navigation/breadcrumb_builder.rb
|
|
256
|
+
- lib/docyard/navigation/page_navigation_builder.rb
|
|
236
257
|
- lib/docyard/navigation/prev_next_builder.rb
|
|
237
|
-
- lib/docyard/navigation/sidebar/
|
|
238
|
-
- lib/docyard/navigation/sidebar/
|
|
239
|
-
- lib/docyard/navigation/sidebar/
|
|
240
|
-
- lib/docyard/navigation/sidebar/
|
|
258
|
+
- lib/docyard/navigation/sidebar/auto_builder.rb
|
|
259
|
+
- lib/docyard/navigation/sidebar/cache.rb
|
|
260
|
+
- lib/docyard/navigation/sidebar/config_builder.rb
|
|
261
|
+
- lib/docyard/navigation/sidebar/distributed_builder.rb
|
|
241
262
|
- lib/docyard/navigation/sidebar/item.rb
|
|
242
263
|
- lib/docyard/navigation/sidebar/local_config_loader.rb
|
|
243
|
-
- lib/docyard/navigation/sidebar/metadata_extractor.rb
|
|
244
|
-
- lib/docyard/navigation/sidebar/metadata_reader.rb
|
|
245
|
-
- lib/docyard/navigation/sidebar/path_prefixer.rb
|
|
246
264
|
- lib/docyard/navigation/sidebar/renderer.rb
|
|
247
|
-
- lib/docyard/navigation/sidebar/sorter.rb
|
|
248
|
-
- lib/docyard/navigation/sidebar/title_extractor.rb
|
|
249
|
-
- lib/docyard/navigation/sidebar/tree_builder.rb
|
|
250
265
|
- lib/docyard/navigation/sidebar/tree_filter.rb
|
|
251
266
|
- lib/docyard/navigation/sidebar_builder.rb
|
|
267
|
+
- lib/docyard/rendering/branding_variables.rb
|
|
252
268
|
- lib/docyard/rendering/icon_helpers.rb
|
|
253
269
|
- lib/docyard/rendering/icons.rb
|
|
254
|
-
- lib/docyard/rendering/icons/
|
|
255
|
-
- lib/docyard/rendering/icons/file_types.rb
|
|
256
|
-
- lib/docyard/rendering/icons/phosphor.rb
|
|
257
|
-
- lib/docyard/rendering/language_mapping.rb
|
|
270
|
+
- lib/docyard/rendering/icons/devicons.rb
|
|
258
271
|
- lib/docyard/rendering/markdown.rb
|
|
272
|
+
- lib/docyard/rendering/og_helpers.rb
|
|
259
273
|
- lib/docyard/rendering/renderer.rb
|
|
260
274
|
- lib/docyard/rendering/template_resolver.rb
|
|
261
275
|
- lib/docyard/routing/fallback_resolver.rb
|
|
@@ -270,6 +284,8 @@ files:
|
|
|
270
284
|
- lib/docyard/server/rack_application.rb
|
|
271
285
|
- lib/docyard/server/resolution_result.rb
|
|
272
286
|
- lib/docyard/server/router.rb
|
|
287
|
+
- lib/docyard/server/sse_server.rb
|
|
288
|
+
- lib/docyard/server/static_file_app.rb
|
|
273
289
|
- lib/docyard/templates/assets/css/code.css
|
|
274
290
|
- lib/docyard/templates/assets/css/components/abbreviation.css
|
|
275
291
|
- lib/docyard/templates/assets/css/components/accordion.css
|
|
@@ -280,6 +296,7 @@ files:
|
|
|
280
296
|
- lib/docyard/templates/assets/css/components/cards.css
|
|
281
297
|
- lib/docyard/templates/assets/css/components/code-block.css
|
|
282
298
|
- lib/docyard/templates/assets/css/components/code-group.css
|
|
299
|
+
- lib/docyard/templates/assets/css/components/feedback.css
|
|
283
300
|
- lib/docyard/templates/assets/css/components/figure.css
|
|
284
301
|
- lib/docyard/templates/assets/css/components/file-tree.css
|
|
285
302
|
- lib/docyard/templates/assets/css/components/heading-anchor.css
|
|
@@ -288,6 +305,7 @@ files:
|
|
|
288
305
|
- lib/docyard/templates/assets/css/components/logo.css
|
|
289
306
|
- lib/docyard/templates/assets/css/components/nav-menu.css
|
|
290
307
|
- lib/docyard/templates/assets/css/components/navigation.css
|
|
308
|
+
- lib/docyard/templates/assets/css/components/page-actions.css
|
|
291
309
|
- lib/docyard/templates/assets/css/components/prev-next.css
|
|
292
310
|
- lib/docyard/templates/assets/css/components/search.css
|
|
293
311
|
- lib/docyard/templates/assets/css/components/steps.css
|
|
@@ -310,6 +328,8 @@ files:
|
|
|
310
328
|
- lib/docyard/templates/assets/js/components/banner.js
|
|
311
329
|
- lib/docyard/templates/assets/js/components/code-block.js
|
|
312
330
|
- lib/docyard/templates/assets/js/components/code-group.js
|
|
331
|
+
- lib/docyard/templates/assets/js/components/copy-page.js
|
|
332
|
+
- lib/docyard/templates/assets/js/components/feedback.js
|
|
313
333
|
- lib/docyard/templates/assets/js/components/file-tree.js
|
|
314
334
|
- lib/docyard/templates/assets/js/components/heading-anchor.js
|
|
315
335
|
- lib/docyard/templates/assets/js/components/lightbox.js
|
|
@@ -320,16 +340,22 @@ files:
|
|
|
320
340
|
- lib/docyard/templates/assets/js/components/table-of-contents.js
|
|
321
341
|
- lib/docyard/templates/assets/js/components/tabs.js
|
|
322
342
|
- lib/docyard/templates/assets/js/components/tooltip.js
|
|
323
|
-
- lib/docyard/templates/assets/js/reload.js
|
|
343
|
+
- lib/docyard/templates/assets/js/hot-reload.js
|
|
324
344
|
- lib/docyard/templates/assets/js/theme.js
|
|
325
345
|
- lib/docyard/templates/assets/logo-dark.svg
|
|
326
346
|
- lib/docyard/templates/assets/logo.svg
|
|
327
347
|
- lib/docyard/templates/config/docyard.yml.erb
|
|
328
348
|
- lib/docyard/templates/errors/404.html.erb
|
|
329
349
|
- lib/docyard/templates/errors/500.html.erb
|
|
350
|
+
- lib/docyard/templates/init/_sidebar.yml
|
|
351
|
+
- lib/docyard/templates/init/docyard.yml
|
|
352
|
+
- lib/docyard/templates/init/pages/components.md
|
|
353
|
+
- lib/docyard/templates/init/pages/getting-started.md
|
|
354
|
+
- lib/docyard/templates/init/pages/index.md
|
|
330
355
|
- lib/docyard/templates/layouts/default.html.erb
|
|
331
356
|
- lib/docyard/templates/layouts/splash.html.erb
|
|
332
357
|
- lib/docyard/templates/partials/_accordion.html.erb
|
|
358
|
+
- lib/docyard/templates/partials/_analytics.html.erb
|
|
333
359
|
- lib/docyard/templates/partials/_banner.html.erb
|
|
334
360
|
- lib/docyard/templates/partials/_breadcrumbs.html.erb
|
|
335
361
|
- lib/docyard/templates/partials/_callout.html.erb
|
|
@@ -337,13 +363,13 @@ files:
|
|
|
337
363
|
- lib/docyard/templates/partials/_code_block.html.erb
|
|
338
364
|
- lib/docyard/templates/partials/_doc_footer.html.erb
|
|
339
365
|
- lib/docyard/templates/partials/_features.html.erb
|
|
366
|
+
- lib/docyard/templates/partials/_feedback.html.erb
|
|
340
367
|
- lib/docyard/templates/partials/_footer.html.erb
|
|
341
368
|
- lib/docyard/templates/partials/_head.html.erb
|
|
342
369
|
- lib/docyard/templates/partials/_header.html.erb
|
|
343
370
|
- lib/docyard/templates/partials/_heading_anchor.html.erb
|
|
344
371
|
- lib/docyard/templates/partials/_hero.html.erb
|
|
345
|
-
- lib/docyard/templates/partials/
|
|
346
|
-
- lib/docyard/templates/partials/_icon_file_extension.html.erb
|
|
372
|
+
- lib/docyard/templates/partials/_icon_library.html.erb
|
|
347
373
|
- lib/docyard/templates/partials/_nav_group.html.erb
|
|
348
374
|
- lib/docyard/templates/partials/_nav_item.html.erb
|
|
349
375
|
- lib/docyard/templates/partials/_nav_leaf.html.erb
|
|
@@ -351,6 +377,7 @@ files:
|
|
|
351
377
|
- lib/docyard/templates/partials/_nav_menu.html.erb
|
|
352
378
|
- lib/docyard/templates/partials/_nav_nested_section.html.erb
|
|
353
379
|
- lib/docyard/templates/partials/_nav_section.html.erb
|
|
380
|
+
- lib/docyard/templates/partials/_page_actions.html.erb
|
|
354
381
|
- lib/docyard/templates/partials/_prev_next.html.erb
|
|
355
382
|
- lib/docyard/templates/partials/_scripts.html.erb
|
|
356
383
|
- lib/docyard/templates/partials/_search_modal.html.erb
|
|
@@ -363,14 +390,15 @@ files:
|
|
|
363
390
|
- lib/docyard/templates/partials/_table_of_contents_toggle.html.erb
|
|
364
391
|
- lib/docyard/templates/partials/_tabs.html.erb
|
|
365
392
|
- lib/docyard/templates/partials/_theme_toggle.html.erb
|
|
366
|
-
- lib/docyard/utils/
|
|
393
|
+
- lib/docyard/utils/git_info.rb
|
|
394
|
+
- lib/docyard/utils/hash_utils.rb
|
|
367
395
|
- lib/docyard/utils/html_helpers.rb
|
|
368
396
|
- lib/docyard/utils/logging.rb
|
|
369
397
|
- lib/docyard/utils/path_resolver.rb
|
|
398
|
+
- lib/docyard/utils/path_utils.rb
|
|
370
399
|
- lib/docyard/utils/text_formatter.rb
|
|
371
400
|
- lib/docyard/utils/url_helpers.rb
|
|
372
401
|
- lib/docyard/version.rb
|
|
373
|
-
- sig/docyard.rbs
|
|
374
402
|
homepage: https://github.com/sanifhimani/docyard
|
|
375
403
|
licenses:
|
|
376
404
|
- MIT
|
|
@@ -379,6 +407,7 @@ metadata:
|
|
|
379
407
|
homepage_uri: https://github.com/sanifhimani/docyard
|
|
380
408
|
source_code_uri: https://github.com/sanifhimani/docyard
|
|
381
409
|
rubygems_mfa_required: 'true'
|
|
410
|
+
post_install_message:
|
|
382
411
|
rdoc_options: []
|
|
383
412
|
require_paths:
|
|
384
413
|
- lib
|
|
@@ -393,7 +422,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
393
422
|
- !ruby/object:Gem::Version
|
|
394
423
|
version: '0'
|
|
395
424
|
requirements: []
|
|
396
|
-
rubygems_version: 3.
|
|
425
|
+
rubygems_version: 3.5.22
|
|
426
|
+
signing_key:
|
|
397
427
|
specification_version: 4
|
|
398
428
|
summary: Documentation generator for Ruby
|
|
399
429
|
test_files: []
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: Bug Report
|
|
3
|
-
about: Report a bug
|
|
4
|
-
title: ''
|
|
5
|
-
labels: bug
|
|
6
|
-
assignees: ''
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Description
|
|
10
|
-
|
|
11
|
-
<!-- Clear description of the bug -->
|
|
12
|
-
|
|
13
|
-
## Steps to Reproduce
|
|
14
|
-
|
|
15
|
-
1.
|
|
16
|
-
2.
|
|
17
|
-
3.
|
|
18
|
-
|
|
19
|
-
## Expected Behavior
|
|
20
|
-
|
|
21
|
-
<!-- What should happen -->
|
|
22
|
-
|
|
23
|
-
## Actual Behavior
|
|
24
|
-
|
|
25
|
-
<!-- What actually happens -->
|
|
26
|
-
|
|
27
|
-
## Environment
|
|
28
|
-
|
|
29
|
-
- Ruby version: <!-- `ruby -v` -->
|
|
30
|
-
- Docyard version: <!-- `gem list docyard` -->
|
|
31
|
-
- OS: <!-- macOS, Linux, etc. -->
|