docyard 0.6.0 → 0.8.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/.rubocop.yml +5 -1
- data/CHANGELOG.md +34 -1
- data/lib/docyard/build/asset_bundler.rb +22 -7
- data/lib/docyard/build/file_copier.rb +49 -27
- data/lib/docyard/build/sitemap_generator.rb +6 -6
- data/lib/docyard/build/static_generator.rb +82 -50
- data/lib/docyard/builder.rb +20 -10
- data/lib/docyard/cli.rb +6 -3
- data/lib/docyard/components/aliases.rb +29 -0
- data/lib/docyard/components/processors/callout_processor.rb +124 -0
- data/lib/docyard/components/processors/code_block_diff_preprocessor.rb +106 -0
- data/lib/docyard/components/processors/code_block_focus_preprocessor.rb +79 -0
- data/lib/docyard/components/processors/code_block_options_preprocessor.rb +78 -0
- data/lib/docyard/components/processors/code_block_processor.rb +175 -0
- data/lib/docyard/components/processors/code_snippet_import_preprocessor.rb +127 -0
- data/lib/docyard/components/processors/heading_anchor_processor.rb +39 -0
- data/lib/docyard/components/processors/icon_processor.rb +53 -0
- data/lib/docyard/components/processors/table_of_contents_processor.rb +68 -0
- data/lib/docyard/components/processors/table_wrapper_processor.rb +22 -0
- data/lib/docyard/components/processors/tabs_processor.rb +48 -0
- data/lib/docyard/components/support/code_block/feature_extractor.rb +117 -0
- data/lib/docyard/components/support/code_block/icon_detector.rb +44 -0
- data/lib/docyard/components/support/code_block/line_parser.rb +84 -0
- data/lib/docyard/components/support/code_block/line_wrapper.rb +50 -0
- data/lib/docyard/components/support/code_block/patterns.rb +55 -0
- data/lib/docyard/components/support/code_detector.rb +61 -0
- data/lib/docyard/components/support/tabs/icon_detector.rb +62 -0
- data/lib/docyard/components/support/tabs/parser.rb +195 -0
- data/lib/docyard/components/support/tabs/range_finder.rb +46 -0
- data/lib/docyard/config/branding_resolver.rb +183 -0
- data/lib/docyard/{constants.rb → config/constants.rb} +7 -4
- data/lib/docyard/config/validator.rb +122 -99
- data/lib/docyard/config.rb +38 -36
- data/lib/docyard/initializer.rb +15 -76
- data/lib/docyard/navigation/breadcrumb_builder.rb +133 -0
- data/lib/docyard/{prev_next_builder.rb → navigation/prev_next_builder.rb} +6 -3
- data/lib/docyard/navigation/sidebar/children_discoverer.rb +51 -0
- data/lib/docyard/navigation/sidebar/config_parser.rb +208 -0
- data/lib/docyard/navigation/sidebar/file_resolver.rb +78 -0
- data/lib/docyard/{sidebar → navigation/sidebar}/file_system_scanner.rb +2 -1
- data/lib/docyard/navigation/sidebar/item.rb +96 -0
- data/lib/docyard/navigation/sidebar/local_config_loader.rb +51 -0
- data/lib/docyard/navigation/sidebar/metadata_extractor.rb +69 -0
- data/lib/docyard/navigation/sidebar/metadata_reader.rb +47 -0
- data/lib/docyard/navigation/sidebar/path_prefixer.rb +34 -0
- data/lib/docyard/navigation/sidebar/renderer.rb +144 -0
- data/lib/docyard/navigation/sidebar/sorter.rb +21 -0
- data/lib/docyard/navigation/sidebar/tree_builder.rb +139 -0
- data/lib/docyard/navigation/sidebar/tree_filter.rb +55 -0
- data/lib/docyard/navigation/sidebar_builder.rb +159 -0
- data/lib/docyard/rendering/icon_helpers.rb +13 -0
- data/lib/docyard/{icons → rendering/icons}/phosphor.rb +26 -1
- data/lib/docyard/{markdown.rb → rendering/markdown.rb} +19 -13
- data/lib/docyard/rendering/renderer.rb +163 -0
- data/lib/docyard/rendering/template_resolver.rb +172 -0
- data/lib/docyard/routing/fallback_resolver.rb +92 -0
- data/lib/docyard/search/build_indexer.rb +74 -0
- data/lib/docyard/search/dev_indexer.rb +155 -0
- data/lib/docyard/search/pagefind_support.rb +33 -0
- data/lib/docyard/{asset_handler.rb → server/asset_handler.rb} +24 -19
- data/lib/docyard/{server.rb → server/dev_server.rb} +32 -9
- data/lib/docyard/server/pagefind_handler.rb +63 -0
- data/lib/docyard/{preview_server.rb → server/preview_server.rb} +2 -2
- data/lib/docyard/server/rack_application.rb +192 -0
- data/lib/docyard/server/resolution_result.rb +29 -0
- data/lib/docyard/{router.rb → server/router.rb} +4 -4
- data/lib/docyard/templates/assets/css/code.css +18 -51
- data/lib/docyard/templates/assets/css/components/breadcrumbs.css +143 -0
- data/lib/docyard/templates/assets/css/components/callout.css +67 -67
- data/lib/docyard/templates/assets/css/components/code-block.css +180 -282
- data/lib/docyard/templates/assets/css/components/heading-anchor.css +28 -15
- data/lib/docyard/templates/assets/css/components/icon.css +0 -1
- data/lib/docyard/templates/assets/css/components/logo.css +0 -2
- data/lib/docyard/templates/assets/css/components/nav-menu.css +237 -0
- data/lib/docyard/templates/assets/css/components/navigation.css +186 -167
- data/lib/docyard/templates/assets/css/components/prev-next.css +76 -47
- data/lib/docyard/templates/assets/css/components/search.css +561 -0
- data/lib/docyard/templates/assets/css/components/tab-bar.css +163 -0
- data/lib/docyard/templates/assets/css/components/table-of-contents.css +127 -114
- data/lib/docyard/templates/assets/css/components/tabs.css +119 -160
- data/lib/docyard/templates/assets/css/components/theme-toggle.css +48 -44
- data/lib/docyard/templates/assets/css/landing.css +815 -0
- data/lib/docyard/templates/assets/css/layout.css +503 -87
- data/lib/docyard/templates/assets/css/main.css +1 -3
- data/lib/docyard/templates/assets/css/markdown.css +111 -93
- data/lib/docyard/templates/assets/css/reset.css +0 -3
- data/lib/docyard/templates/assets/css/typography.css +43 -41
- data/lib/docyard/templates/assets/css/variables.css +268 -208
- data/lib/docyard/templates/assets/favicon.svg +7 -8
- data/lib/docyard/templates/assets/fonts/Inter-Variable.ttf +0 -0
- data/lib/docyard/templates/assets/js/components/code-block.js +24 -42
- data/lib/docyard/templates/assets/js/components/heading-anchor.js +26 -24
- data/lib/docyard/templates/assets/js/components/navigation.js +181 -70
- data/lib/docyard/templates/assets/js/components/search.js +610 -0
- data/lib/docyard/templates/assets/js/components/sidebar-toggle.js +29 -0
- data/lib/docyard/templates/assets/js/components/tab-navigation.js +145 -0
- data/lib/docyard/templates/assets/js/components/table-of-contents.js +153 -66
- data/lib/docyard/templates/assets/js/components/tabs.js +31 -69
- data/lib/docyard/templates/assets/js/theme.js +0 -3
- data/lib/docyard/templates/assets/logo-dark.svg +8 -2
- data/lib/docyard/templates/assets/logo.svg +7 -4
- data/lib/docyard/templates/config/docyard.yml.erb +37 -34
- data/lib/docyard/templates/errors/404.html.erb +1 -1
- data/lib/docyard/templates/errors/500.html.erb +1 -1
- data/lib/docyard/templates/layouts/default.html.erb +19 -56
- data/lib/docyard/templates/layouts/splash.html.erb +176 -0
- data/lib/docyard/templates/partials/_breadcrumbs.html.erb +24 -0
- data/lib/docyard/templates/partials/_code_block.html.erb +6 -4
- data/lib/docyard/templates/partials/_doc_footer.html.erb +25 -0
- data/lib/docyard/templates/partials/_features.html.erb +15 -0
- data/lib/docyard/templates/partials/_footer.html.erb +42 -0
- data/lib/docyard/templates/partials/_head.html.erb +22 -0
- data/lib/docyard/templates/partials/_header.html.erb +49 -0
- data/lib/docyard/templates/partials/_heading_anchor.html.erb +3 -1
- data/lib/docyard/templates/partials/_hero.html.erb +27 -0
- data/lib/docyard/templates/partials/_nav_group.html.erb +25 -11
- data/lib/docyard/templates/partials/_nav_leaf.html.erb +1 -1
- data/lib/docyard/templates/partials/_nav_menu.html.erb +42 -0
- data/lib/docyard/templates/partials/_nav_nested_section.html.erb +11 -0
- data/lib/docyard/templates/partials/_nav_section.html.erb +1 -1
- data/lib/docyard/templates/partials/_prev_next.html.erb +9 -3
- data/lib/docyard/templates/partials/_scripts.html.erb +7 -0
- data/lib/docyard/templates/partials/_search_modal.html.erb +41 -0
- data/lib/docyard/templates/partials/_search_trigger.html.erb +18 -0
- data/lib/docyard/templates/partials/_sidebar.html.erb +21 -4
- data/lib/docyard/templates/partials/_tab_bar.html.erb +25 -0
- data/lib/docyard/templates/partials/_table_of_contents.html.erb +12 -12
- data/lib/docyard/templates/partials/_table_of_contents_toggle.html.erb +1 -3
- data/lib/docyard/templates/partials/_tabs.html.erb +2 -2
- data/lib/docyard/templates/partials/_theme_toggle.html.erb +2 -11
- data/lib/docyard/utils/html_helpers.rb +14 -0
- data/lib/docyard/utils/path_resolver.rb +2 -1
- data/lib/docyard/utils/url_helpers.rb +20 -0
- data/lib/docyard/version.rb +1 -1
- data/lib/docyard.rb +22 -15
- metadata +89 -50
- data/lib/docyard/components/callout_processor.rb +0 -121
- data/lib/docyard/components/code_block_diff_preprocessor.rb +0 -104
- data/lib/docyard/components/code_block_feature_extractor.rb +0 -113
- data/lib/docyard/components/code_block_focus_preprocessor.rb +0 -77
- data/lib/docyard/components/code_block_icon_detector.rb +0 -40
- data/lib/docyard/components/code_block_line_wrapper.rb +0 -46
- data/lib/docyard/components/code_block_options_preprocessor.rb +0 -76
- data/lib/docyard/components/code_block_patterns.rb +0 -51
- data/lib/docyard/components/code_block_processor.rb +0 -176
- data/lib/docyard/components/code_detector.rb +0 -59
- data/lib/docyard/components/code_line_parser.rb +0 -80
- data/lib/docyard/components/code_snippet_import_preprocessor.rb +0 -125
- data/lib/docyard/components/heading_anchor_processor.rb +0 -34
- data/lib/docyard/components/icon_detector.rb +0 -57
- data/lib/docyard/components/icon_processor.rb +0 -51
- data/lib/docyard/components/table_of_contents_processor.rb +0 -64
- data/lib/docyard/components/table_wrapper_processor.rb +0 -18
- data/lib/docyard/components/tabs_parser.rb +0 -191
- data/lib/docyard/components/tabs_processor.rb +0 -44
- data/lib/docyard/components/tabs_range_finder.rb +0 -42
- data/lib/docyard/rack_application.rb +0 -172
- data/lib/docyard/renderer.rb +0 -120
- data/lib/docyard/routing/resolution_result.rb +0 -31
- data/lib/docyard/sidebar/config_parser.rb +0 -180
- data/lib/docyard/sidebar/item.rb +0 -58
- data/lib/docyard/sidebar/renderer.rb +0 -137
- data/lib/docyard/sidebar/tree_builder.rb +0 -59
- data/lib/docyard/sidebar_builder.rb +0 -102
- data/lib/docyard/templates/markdown/getting-started/installation.md.erb +0 -77
- data/lib/docyard/templates/markdown/guides/configuration.md.erb +0 -202
- data/lib/docyard/templates/markdown/guides/markdown-features.md.erb +0 -247
- data/lib/docyard/templates/markdown/index.md.erb +0 -82
- /data/lib/docyard/{sidebar → navigation/sidebar}/title_extractor.rb +0 -0
- /data/lib/docyard/{icons → rendering/icons}/LICENSE.phosphor +0 -0
- /data/lib/docyard/{icons → rendering/icons}/file_types.rb +0 -0
- /data/lib/docyard/{icons.rb → rendering/icons.rb} +0 -0
- /data/lib/docyard/{language_mapping.rb → rendering/language_mapping.rb} +0 -0
- /data/lib/docyard/{file_watcher.rb → server/file_watcher.rb} +0 -0
- /data/lib/docyard/{errors.rb → utils/errors.rb} +0 -0
- /data/lib/docyard/{logging.rb → utils/logging.rb} +0 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "erb"
|
|
4
|
+
require_relative "../../rendering/icon_helpers"
|
|
5
|
+
|
|
6
|
+
module Docyard
|
|
7
|
+
module Sidebar
|
|
8
|
+
class Renderer
|
|
9
|
+
include Utils::UrlHelpers
|
|
10
|
+
include IconHelpers
|
|
11
|
+
|
|
12
|
+
PARTIALS_PATH = File.join(__dir__, "../../templates/partials")
|
|
13
|
+
|
|
14
|
+
attr_reader :site_title, :base_url, :header_ctas
|
|
15
|
+
|
|
16
|
+
def initialize(site_title: "Documentation", base_url: "/", header_ctas: [])
|
|
17
|
+
@site_title = site_title
|
|
18
|
+
@base_url = normalize_base_url(base_url)
|
|
19
|
+
@header_ctas = header_ctas
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def render(tree)
|
|
23
|
+
return "" if tree.empty?
|
|
24
|
+
|
|
25
|
+
nav_content = render_tree_with_sections(tree)
|
|
26
|
+
render_partial(:sidebar, nav_content: nav_content, header_ctas: header_ctas)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def render_partial(name, locals = {})
|
|
32
|
+
template_path = File.join(PARTIALS_PATH, "_#{name}.html.erb")
|
|
33
|
+
template = File.read(template_path)
|
|
34
|
+
|
|
35
|
+
locals.each { |key, value| instance_variable_set("@#{key}", value) }
|
|
36
|
+
|
|
37
|
+
erb_binding = binding
|
|
38
|
+
ERB.new(template).result(erb_binding)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def render_tree_with_sections(items)
|
|
42
|
+
filtered_items = items.reject { |item| item[:title]&.downcase == site_title.downcase }
|
|
43
|
+
grouped = group_items_by_section(filtered_items)
|
|
44
|
+
|
|
45
|
+
grouped.map do |group|
|
|
46
|
+
if group[:section]
|
|
47
|
+
render_section(group[:item])
|
|
48
|
+
else
|
|
49
|
+
render_item_group(group[:items])
|
|
50
|
+
end
|
|
51
|
+
end.join
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def group_items_by_section(items)
|
|
55
|
+
groups = []
|
|
56
|
+
current_non_section_items = []
|
|
57
|
+
|
|
58
|
+
items.each do |item|
|
|
59
|
+
if item[:section]
|
|
60
|
+
if current_non_section_items.any?
|
|
61
|
+
groups << { section: false, items: current_non_section_items }
|
|
62
|
+
current_non_section_items = []
|
|
63
|
+
end
|
|
64
|
+
groups << { section: true, item: item }
|
|
65
|
+
else
|
|
66
|
+
current_non_section_items << item
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
groups << { section: false, items: current_non_section_items } if current_non_section_items.any?
|
|
71
|
+
groups
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def render_section(item)
|
|
75
|
+
section_content = render_tree(item[:children])
|
|
76
|
+
render_partial(:nav_section,
|
|
77
|
+
section_name: item[:title],
|
|
78
|
+
section_icon: item[:icon],
|
|
79
|
+
section_content: section_content)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def render_item_group(items)
|
|
83
|
+
render_partial(:nav_section,
|
|
84
|
+
section_name: nil,
|
|
85
|
+
section_icon: nil,
|
|
86
|
+
section_content: render_tree(items))
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def render_tree(items)
|
|
90
|
+
return "" if items.empty?
|
|
91
|
+
|
|
92
|
+
list_items = items.map { |item| render_item(item) }.join
|
|
93
|
+
render_partial(:nav_list, list_items: list_items)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def render_item(item)
|
|
97
|
+
item_content = if item[:children].empty?
|
|
98
|
+
render_leaf_item(item)
|
|
99
|
+
elsif item[:section]
|
|
100
|
+
render_nested_section(item)
|
|
101
|
+
else
|
|
102
|
+
render_group_item(item)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
render_partial(:nav_item, item_content: item_content)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def render_leaf_item(item)
|
|
109
|
+
render_partial(
|
|
110
|
+
:nav_leaf,
|
|
111
|
+
path: item[:path],
|
|
112
|
+
title: item[:title],
|
|
113
|
+
active: item[:active],
|
|
114
|
+
icon: item[:icon],
|
|
115
|
+
target: item[:target]
|
|
116
|
+
)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def render_nested_section(item)
|
|
120
|
+
children_html = render_tree(item[:children])
|
|
121
|
+
render_partial(
|
|
122
|
+
:nav_nested_section,
|
|
123
|
+
title: item[:title],
|
|
124
|
+
icon: item[:icon],
|
|
125
|
+
children_html: children_html
|
|
126
|
+
)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def render_group_item(item)
|
|
130
|
+
children_html = render_tree(item[:children])
|
|
131
|
+
render_partial(
|
|
132
|
+
:nav_group,
|
|
133
|
+
title: item[:title],
|
|
134
|
+
path: item[:path],
|
|
135
|
+
active: item[:active],
|
|
136
|
+
children_html: children_html,
|
|
137
|
+
icon: item[:icon],
|
|
138
|
+
collapsed: item[:collapsed],
|
|
139
|
+
has_index: item[:has_index]
|
|
140
|
+
)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Docyard
|
|
4
|
+
module Sidebar
|
|
5
|
+
module Sorter
|
|
6
|
+
module_function
|
|
7
|
+
|
|
8
|
+
def sort_by_order(items)
|
|
9
|
+
items.sort_by do |item|
|
|
10
|
+
order = item[:order]
|
|
11
|
+
title = item[:title]&.downcase || ""
|
|
12
|
+
if order.nil?
|
|
13
|
+
[1, title]
|
|
14
|
+
else
|
|
15
|
+
[0, order, title]
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "sorter"
|
|
4
|
+
require_relative "local_config_loader"
|
|
5
|
+
require_relative "config_parser"
|
|
6
|
+
require_relative "metadata_reader"
|
|
7
|
+
|
|
8
|
+
module Docyard
|
|
9
|
+
module Sidebar
|
|
10
|
+
class TreeBuilder
|
|
11
|
+
attr_reader :docs_path, :current_path, :title_extractor, :metadata_reader
|
|
12
|
+
|
|
13
|
+
def initialize(docs_path:, current_path:, title_extractor: TitleExtractor.new)
|
|
14
|
+
@docs_path = docs_path
|
|
15
|
+
@current_path = Utils::PathResolver.normalize(current_path)
|
|
16
|
+
@title_extractor = title_extractor
|
|
17
|
+
@metadata_reader = MetadataReader.new
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def build(file_items)
|
|
21
|
+
transform_items(file_items, "", depth: 1)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def transform_items(items, relative_base, depth:)
|
|
27
|
+
transformed = items.map do |item|
|
|
28
|
+
if item[:type] == :directory
|
|
29
|
+
transform_directory(item, relative_base, depth: depth)
|
|
30
|
+
else
|
|
31
|
+
transform_file(item, relative_base)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
Sorter.sort_by_order(transformed)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def transform_directory(item, relative_base, depth:)
|
|
38
|
+
dir_path = File.join(relative_base, item[:name])
|
|
39
|
+
dir_context = build_directory_context(dir_path)
|
|
40
|
+
children = build_directory_children(item, dir_path, depth)
|
|
41
|
+
|
|
42
|
+
if depth == 1
|
|
43
|
+
build_section(item, children, dir_context)
|
|
44
|
+
else
|
|
45
|
+
build_collapsible_group(item, children, dir_context)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def build_directory_children(item, dir_path, depth)
|
|
50
|
+
full_dir_path = File.join(docs_path, dir_path)
|
|
51
|
+
local_config = LocalConfigLoader.new(full_dir_path).load
|
|
52
|
+
|
|
53
|
+
if local_config
|
|
54
|
+
build_children_from_config(local_config, dir_path)
|
|
55
|
+
else
|
|
56
|
+
transform_items(item[:children], dir_path, depth: depth + 1)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def build_children_from_config(config_items, base_path)
|
|
61
|
+
full_base_path = File.join(docs_path, base_path)
|
|
62
|
+
parser = ConfigParser.new(config_items, docs_path: full_base_path, current_path: current_path)
|
|
63
|
+
parser.parse.map(&:to_h)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def build_directory_context(dir_path)
|
|
67
|
+
index_file_path = File.join(docs_path, dir_path, "index.md")
|
|
68
|
+
has_index = File.file?(index_file_path)
|
|
69
|
+
{ index_file_path: index_file_path, has_index: has_index,
|
|
70
|
+
url_path: has_index ? Utils::PathResolver.to_url(dir_path) : nil }
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def build_section(item, children, context)
|
|
74
|
+
filtered_children = filter_index_from_children(children, context[:url_path])
|
|
75
|
+
metadata = context[:has_index] ? metadata_reader.extract_index_metadata(context[:index_file_path]) : {}
|
|
76
|
+
|
|
77
|
+
if context[:has_index]
|
|
78
|
+
overview = build_overview_item(metadata, context[:url_path])
|
|
79
|
+
filtered_children = [overview] + filtered_children
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
build_section_hash(item, filtered_children, metadata)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def build_section_hash(item, children, metadata)
|
|
86
|
+
{ title: Utils::TextFormatter.titleize(item[:name]), path: nil, icon: metadata[:icon],
|
|
87
|
+
active: false, type: :directory, section: true,
|
|
88
|
+
collapsed: false, has_index: false, order: metadata[:order], children: children }
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def build_collapsible_group(item, children, context)
|
|
92
|
+
filtered_children = filter_index_from_children(children, context[:url_path])
|
|
93
|
+
metadata = context[:has_index] ? metadata_reader.extract_index_metadata(context[:index_file_path]) : {}
|
|
94
|
+
is_active = context[:has_index] && current_path == context[:url_path]
|
|
95
|
+
|
|
96
|
+
build_collapsible_hash(item, filtered_children, context, metadata, is_active)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def build_collapsible_hash(item, children, context, metadata, is_active)
|
|
100
|
+
{ title: Utils::TextFormatter.titleize(item[:name]), path: context[:url_path],
|
|
101
|
+
icon: metadata[:icon], active: is_active, type: :directory, section: false,
|
|
102
|
+
collapsed: collapsible_collapsed?(children, is_active), has_index: context[:has_index],
|
|
103
|
+
order: metadata[:order], children: children }
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def collapsible_collapsed?(children, is_active)
|
|
107
|
+
return false if is_active || active_child?(children)
|
|
108
|
+
|
|
109
|
+
true
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def build_overview_item(metadata, url_path)
|
|
113
|
+
{ title: metadata[:sidebar_text] || "Overview", path: url_path,
|
|
114
|
+
icon: metadata[:icon], active: current_path == url_path, type: :file, children: [] }
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def filter_index_from_children(children, index_url_path)
|
|
118
|
+
return children unless index_url_path
|
|
119
|
+
|
|
120
|
+
children.reject { |child| child[:path] == index_url_path }
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def active_child?(children)
|
|
124
|
+
children.any? { |child| child[:active] || active_child?(child[:children] || []) }
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def transform_file(item, relative_base)
|
|
128
|
+
file_path = File.join(relative_base, "#{item[:name]}#{Constants::MARKDOWN_EXTENSION}")
|
|
129
|
+
full_file_path = File.join(docs_path, file_path)
|
|
130
|
+
url_path = Utils::PathResolver.to_url(file_path.delete_suffix(Constants::MARKDOWN_EXTENSION))
|
|
131
|
+
metadata = metadata_reader.extract_file_metadata(full_file_path)
|
|
132
|
+
|
|
133
|
+
{ title: metadata[:title] || title_extractor.extract(full_file_path),
|
|
134
|
+
path: url_path, icon: metadata[:icon], active: current_path == url_path,
|
|
135
|
+
type: :file, order: metadata[:order], children: [] }
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Docyard
|
|
4
|
+
module Sidebar
|
|
5
|
+
class TreeFilter
|
|
6
|
+
def initialize(tree, tab_path)
|
|
7
|
+
@tree = tree
|
|
8
|
+
@tab_path = tab_path
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def filter
|
|
12
|
+
@tree.filter_map { |item| filter_item(item) }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def filter_item(item)
|
|
18
|
+
children = item[:children] || []
|
|
19
|
+
|
|
20
|
+
if children.any?
|
|
21
|
+
filter_parent_item(item, children)
|
|
22
|
+
else
|
|
23
|
+
filter_leaf_item(item)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def filter_parent_item(item, children)
|
|
28
|
+
filtered_children = self.class.new(children, @tab_path).filter
|
|
29
|
+
has_matching_content = filtered_children.any? { |c| !external_item?(c) }
|
|
30
|
+
|
|
31
|
+
return nil if !has_matching_content && !item_matches_path?(item[:path])
|
|
32
|
+
|
|
33
|
+
item.merge(children: filtered_children)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def filter_leaf_item(item)
|
|
37
|
+
return item if external_item?(item)
|
|
38
|
+
return nil unless item_matches_path?(item[:path])
|
|
39
|
+
|
|
40
|
+
item
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def external_item?(item)
|
|
44
|
+
item[:type] == :external || item[:path]&.start_with?("http")
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def item_matches_path?(item_path)
|
|
48
|
+
return false if item_path.nil?
|
|
49
|
+
|
|
50
|
+
normalized_path = item_path.chomp("/")
|
|
51
|
+
normalized_path == @tab_path || normalized_path.start_with?("#{@tab_path}/")
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "sidebar/file_system_scanner"
|
|
4
|
+
require_relative "sidebar/title_extractor"
|
|
5
|
+
require_relative "sidebar/tree_builder"
|
|
6
|
+
require_relative "sidebar/renderer"
|
|
7
|
+
require_relative "sidebar/config_parser"
|
|
8
|
+
require_relative "sidebar/local_config_loader"
|
|
9
|
+
require_relative "sidebar/path_prefixer"
|
|
10
|
+
require_relative "sidebar/tree_filter"
|
|
11
|
+
|
|
12
|
+
module Docyard
|
|
13
|
+
class SidebarBuilder
|
|
14
|
+
attr_reader :docs_path, :current_path, :config, :header_ctas
|
|
15
|
+
|
|
16
|
+
def initialize(docs_path:, current_path: "/", config: nil, header_ctas: [])
|
|
17
|
+
@docs_path = docs_path
|
|
18
|
+
@current_path = current_path
|
|
19
|
+
@config = config
|
|
20
|
+
@header_ctas = header_ctas
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def tree
|
|
24
|
+
@tree ||= build_scoped_tree
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def to_html
|
|
28
|
+
renderer.render(tree)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def build_scoped_tree
|
|
34
|
+
active_tab = find_active_tab
|
|
35
|
+
return build_tree_for_path(docs_path) unless active_tab
|
|
36
|
+
|
|
37
|
+
build_tree_for_tab(active_tab)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def build_tree_for_tab(tab)
|
|
41
|
+
tab_path = tab["href"]&.chomp("/")
|
|
42
|
+
return build_tree_for_path(docs_path) if empty_tab_path?(tab_path)
|
|
43
|
+
|
|
44
|
+
scoped_docs_path = resolve_scoped_path(tab_path)
|
|
45
|
+
build_scoped_or_filtered_tree(scoped_docs_path, tab_path)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def empty_tab_path?(tab_path)
|
|
49
|
+
tab_path.nil? || tab_path.empty? || tab_path == "/"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def resolve_scoped_path(tab_path)
|
|
53
|
+
tab_folder = tab_path.sub(%r{^/}, "")
|
|
54
|
+
File.join(docs_path, tab_folder)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def build_scoped_or_filtered_tree(scoped_docs_path, tab_path)
|
|
58
|
+
if scoped_sidebar_available?(scoped_docs_path)
|
|
59
|
+
build_tree_for_path(scoped_docs_path, base_url_prefix: tab_path)
|
|
60
|
+
else
|
|
61
|
+
Sidebar::TreeFilter.new(build_tree_for_path(docs_path), tab_path).filter
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def scoped_sidebar_available?(path)
|
|
66
|
+
File.directory?(path) && Sidebar::LocalConfigLoader.new(path).config_file_exists?
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def build_tree_for_path(path, base_url_prefix: "")
|
|
70
|
+
config_items = Sidebar::LocalConfigLoader.new(path).load
|
|
71
|
+
tree = build_tree(config_items, path, base_url_prefix)
|
|
72
|
+
maybe_prepend_overview(tree, path, base_url_prefix)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def build_tree(config_items, path, base_url_prefix)
|
|
76
|
+
if config_items&.any?
|
|
77
|
+
build_tree_from_config(config_items, path, base_url_prefix)
|
|
78
|
+
else
|
|
79
|
+
build_tree_from_filesystem(path, base_url_prefix)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def maybe_prepend_overview(tree, path, base_url_prefix)
|
|
84
|
+
return tree if skip_overview?(tree, path, base_url_prefix)
|
|
85
|
+
|
|
86
|
+
[build_overview_item(base_url_prefix)] + tree
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def skip_overview?(tree, path, base_url_prefix)
|
|
90
|
+
base_url_prefix.empty? ||
|
|
91
|
+
tree.first&.dig(:section) ||
|
|
92
|
+
!File.file?(File.join(path, "index.md")) ||
|
|
93
|
+
tree.any? { |item| item[:path] == base_url_prefix }
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def build_overview_item(base_url_prefix)
|
|
97
|
+
{
|
|
98
|
+
title: "Overview", path: base_url_prefix, icon: nil,
|
|
99
|
+
active: current_path == base_url_prefix, type: :file,
|
|
100
|
+
collapsed: false, collapsible: false, target: "_self",
|
|
101
|
+
has_index: false, section: false, children: []
|
|
102
|
+
}
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def build_tree_from_config(items, path, base_url_prefix)
|
|
106
|
+
tree = Sidebar::ConfigParser.new(
|
|
107
|
+
items, docs_path: path, current_path: current_path_relative_to(base_url_prefix)
|
|
108
|
+
).parse.map(&:to_h)
|
|
109
|
+
|
|
110
|
+
Sidebar::PathPrefixer.new(tree, base_url_prefix).prefix
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def build_tree_from_filesystem(path, base_url_prefix)
|
|
114
|
+
file_items = Sidebar::FileSystemScanner.new(path).scan
|
|
115
|
+
tree = Sidebar::TreeBuilder.new(
|
|
116
|
+
docs_path: path, current_path: current_path_relative_to(base_url_prefix)
|
|
117
|
+
).build(file_items)
|
|
118
|
+
|
|
119
|
+
Sidebar::PathPrefixer.new(tree, base_url_prefix).prefix
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def current_path_relative_to(prefix)
|
|
123
|
+
return current_path if prefix.empty?
|
|
124
|
+
return current_path unless current_path.start_with?(prefix)
|
|
125
|
+
|
|
126
|
+
relative = current_path.sub(prefix, "")
|
|
127
|
+
relative.empty? ? "/" : relative
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def renderer
|
|
131
|
+
@renderer ||= Sidebar::Renderer.new(
|
|
132
|
+
site_title: config&.title || "Documentation",
|
|
133
|
+
base_url: config&.build&.base || "/",
|
|
134
|
+
header_ctas: header_ctas
|
|
135
|
+
)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def tabs_configured?
|
|
139
|
+
tabs = config&.tabs
|
|
140
|
+
tabs.is_a?(Array) && tabs.any?
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def find_active_tab
|
|
144
|
+
return nil unless tabs_configured?
|
|
145
|
+
|
|
146
|
+
normalized_current = current_path.chomp("/")
|
|
147
|
+
config.tabs.find { |tab| tab_matches_current?(tab, normalized_current) }
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def tab_matches_current?(tab, normalized_current)
|
|
151
|
+
return false if tab["external"]
|
|
152
|
+
|
|
153
|
+
tab_href = tab["href"]&.chomp("/")
|
|
154
|
+
return false if tab_href.nil?
|
|
155
|
+
|
|
156
|
+
normalized_current == tab_href || normalized_current.start_with?("#{tab_href}/")
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Docyard
|
|
4
|
+
module IconHelpers
|
|
5
|
+
def icon(name, weight = "regular")
|
|
6
|
+
Icons.render(name.to_s.tr("_", "-"), weight) || ""
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def icon_file_extension(extension)
|
|
10
|
+
Icons.render_file_extension(extension) || ""
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -36,7 +36,32 @@ module Docyard
|
|
|
36
36
|
"siren" => '<path d="M120,16V8a8,8,0,0,1,16,0v8a8,8,0,0,1-16,0Zm80,32a8,8,0,0,0,5.66-2.34l8-8a8,8,0,0,0-11.32-11.32l-8,8A8,8,0,0,0,200,48ZM50.34,45.66A8,8,0,0,0,61.66,34.34l-8-8A8,8,0,0,0,42.34,37.66Zm87,26.45a8,8,0,1,0-2.64,15.78C153.67,91.08,168,108.32,168,128a8,8,0,0,0,16,0C184,100.6,163.93,76.57,137.32,72.11ZM232,176v24a16,16,0,0,1-16,16H40a16,16,0,0,1-16-16V176a16,16,0,0,1,16-16V128a88,88,0,0,1,88.67-88c48.15.36,87.33,40.29,87.33,89v31A16,16,0,0,1,232,176ZM56,160H200V129c0-40-32.05-72.71-71.45-73H128a72,72,0,0,0-72,72Zm160,40V176H40v24H216Z"/>',
|
|
37
37
|
"file" => '<path d="M213.66,82.34l-56-56A8,8,0,0,0,152,24H56A16,16,0,0,0,40,40V216a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V88A8,8,0,0,0,213.66,82.34ZM160,51.31,188.69,80H160ZM200,216H56V40h88V88a8,8,0,0,0,8,8h48V216Z"/>',
|
|
38
38
|
"terminal-window" => '<path d="M128,128a8,8,0,0,1-3,6.25l-40,32a8,8,0,1,1-10-12.5L107.19,128,75,102.25a8,8,0,1,1,10-12.5l40,32A8,8,0,0,1,128,128Zm48,24H136a8,8,0,0,0,0,16h40a8,8,0,0,0,0-16Zm56-96V200a16,16,0,0,1-16,16H40a16,16,0,0,1-16-16V56A16,16,0,0,1,40,40H216A16,16,0,0,1,232,56ZM216,200V56H40V200H216Z"/>',
|
|
39
|
-
"list-dashes" => '<path d="M88,64a8,8,0,0,1,8-8H216a8,8,0,0,1,0,16H96A8,8,0,0,1,88,64Zm128,56H96a8,8,0,0,0,0,16H216a8,8,0,0,0,0-16Zm0,64H96a8,8,0,0,0,0,16H216a8,8,0,0,0,0-16ZM56,56H40a8,8,0,0,0,0,16H56a8,8,0,0,0,0-16Zm0,64H40a8,8,0,0,0,0,16H56a8,8,0,0,0,0-16Zm0,64H40a8,8,0,0,0,0,16H56a8,8,0,0,0,0-16Z"/>'
|
|
39
|
+
"list-dashes" => '<path d="M88,64a8,8,0,0,1,8-8H216a8,8,0,0,1,0,16H96A8,8,0,0,1,88,64Zm128,56H96a8,8,0,0,0,0,16H216a8,8,0,0,0,0-16Zm0,64H96a8,8,0,0,0,0,16H216a8,8,0,0,0,0-16ZM56,56H40a8,8,0,0,0,0,16H56a8,8,0,0,0,0-16Zm0,64H40a8,8,0,0,0,0,16H56a8,8,0,0,0,0-16Zm0,64H40a8,8,0,0,0,0,16H56a8,8,0,0,0,0-16Z"/>',
|
|
40
|
+
"magnifying-glass" => '<path d="M229.66,218.34l-50.07-50.06a88.11,88.11,0,1,0-11.31,11.31l50.06,50.07a8,8,0,0,0,11.32-11.32ZM40,112a72,72,0,1,1,72,72A72.08,72.08,0,0,1,40,112Z"/>',
|
|
41
|
+
"command" => '<path d="M180,144H160V112h20a36,36,0,1,0-36-36V96H112V76a36,36,0,1,0-36,36H96v32H76a36,36,0,1,0,36,36V160h32v20a36,36,0,1,0,36-36ZM160,76a20,20,0,1,1,20,20H160ZM56,76a20,20,0,0,1,40,0V96H76A20,20,0,0,1,56,76ZM96,180a20,20,0,1,1-20-20H96Zm16-68h32v32H112Zm68,88a20,20,0,0,1-20-20V160h20a20,20,0,0,1,0,40Z"/>',
|
|
42
|
+
"hash" => '<path d="M224,88H175.4l8.47-46.57a8,8,0,0,0-15.74-2.86l-9,49.43H111.4l8.47-46.57a8,8,0,0,0-15.74-2.86L95.14,88H48a8,8,0,0,0,0,16H92.23L83.5,152H32a8,8,0,0,0,0,16H80.6l-8.47,46.57a8,8,0,0,0,6.44,9.3A7.79,7.79,0,0,0,80,224a8,8,0,0,0,7.86-6.57l9-49.43H144.6l-8.47,46.57a8,8,0,0,0,6.44,9.3,7.79,7.79,0,0,0,1.43.13,8,8,0,0,0,7.86-6.57l9-49.43H208a8,8,0,0,0,0-16H163.77l8.73-48H224a8,8,0,0,0,0-16Zm-68.5,64H107.77l8.73-48h47.73Z"/>',
|
|
43
|
+
"table" => '<path d="M224,48H32a8,8,0,0,0-8,8V192a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A8,8,0,0,0,224,48ZM40,112H80v32H40Zm56,0H216v32H96Zm120-48v32H40V64ZM40,160H80v32H40Zm176,32H96V160H216v32Z"/>',
|
|
44
|
+
"caret-down" => '<path d="M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z"/>',
|
|
45
|
+
"sidebar" => '<path d="M216,40H40A16,16,0,0,0,24,56V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40ZM40,56H80V200H40ZM216,200H96V56H216V200Z"/>',
|
|
46
|
+
"link-simple" => '<path d="M165.66,90.34a8,8,0,0,1,0,11.32l-64,64a8,8,0,0,1-11.32-11.32l64-64A8,8,0,0,1,165.66,90.34ZM215.6,40.4a56,56,0,0,0-79.2,0L106.34,70.45a8,8,0,0,0,11.32,11.32l30.06-30a40,40,0,0,1,56.57,56.56l-30.07,30.06a8,8,0,0,0,11.31,11.32L215.6,119.6a56,56,0,0,0,0-79.2ZM138.34,174.22l-30.06,30.06a40,40,0,1,1-56.56-56.56l30.05-30.06a8,8,0,0,0-11.32-11.32L40.4,136.4a56,56,0,0,0,79.2,79.2l30.06-30.07a8,8,0,0,0-11.32-11.31Z"/>',
|
|
47
|
+
"copyright" => '<path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216ZM96,128a32,32,0,0,0,57.6,19.2,8,8,0,0,1,12.8,9.61,48,48,0,1,1,0-57.62,8,8,0,0,1-12.8,9.61A32,32,0,0,0,96,128Z"/>',
|
|
48
|
+
"equals" => '<path d="M224,160a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,160ZM40,104H216a8,8,0,0,0,0-16H40a8,8,0,0,0,0,16Z"/>',
|
|
49
|
+
"x-logo" => '<path d="M214.75,211.71l-62.6-98.38,61.77-67.95a8,8,0,0,0-11.84-10.76L143.24,99.34,102.75,35.71A8,8,0,0,0,96,32H48a8,8,0,0,0-6.75,12.3l62.6,98.37-61.77,68a8,8,0,1,0,11.84,10.76l58.84-64.72,40.49,63.63A8,8,0,0,0,160,224h48a8,8,0,0,0,6.75-12.29ZM164.39,208,62.57,48h29L193.43,208Z"/>',
|
|
50
|
+
"discord-logo" => '<path d="M104,140a12,12,0,1,1-12-12A12,12,0,0,1,104,140Zm60-12a12,12,0,1,0,12,12A12,12,0,0,0,164,128Zm74.45,64.9-67,29.71a16.17,16.17,0,0,1-21.71-9.1l-8.11-22q-6.72.45-13.63.46t-13.63-.46l-8.11,22a16.18,16.18,0,0,1-21.71,9.1l-67-29.71a15.93,15.93,0,0,1-9.06-18.51L38,58A16.07,16.07,0,0,1,51,46.14l36.06-5.93a16.22,16.22,0,0,1,18.26,11.88l3.26,12.84Q118.11,64,128,64t19.4.93l3.26-12.84a16.21,16.21,0,0,1,18.26-11.88L205,46.14A16.07,16.07,0,0,1,218,58l29.53,116.38A15.93,15.93,0,0,1,238.45,192.9ZM232,178.28,202.47,62s0,0-.08,0L166.33,56a.17.17,0,0,0-.17,0l-2.83,11.14c5,.94,10,2.06,14.83,3.42A8,8,0,0,1,176,86.31a8.09,8.09,0,0,1-2.16-.3A172.25,172.25,0,0,0,128,80a172.25,172.25,0,0,0-45.84,6,8,8,0,1,1-4.32-15.4c4.82-1.36,9.78-2.48,14.82-3.42L89.83,56s0,0-.12,0h0L53.61,61.93a.17.17,0,0,0-.09,0L24,178.33,91,208a.23.23,0,0,0,.22,0L98,189.72a173.2,173.2,0,0,1-20.14-4.32A8,8,0,0,1,82.16,170,171.85,171.85,0,0,0,128,176a171.85,171.85,0,0,0,45.84-6,8,8,0,0,1,4.32,15.41A173.2,173.2,0,0,1,158,189.72L164.75,208a.22.22,0,0,0,.21,0Z"/>',
|
|
51
|
+
"linkedin-logo" => '<path d="M216,24H40A16,16,0,0,0,24,40V216a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V40A16,16,0,0,0,216,24Zm0,192H40V40H216V216ZM96,112v64a8,8,0,0,1-16,0V112a8,8,0,0,1,16,0Zm88,28v36a8,8,0,0,1-16,0V140a20,20,0,0,0-40,0v36a8,8,0,0,1-16,0V112a8,8,0,0,1,15.79-1.78A36,36,0,0,1,184,140ZM100,84A12,12,0,1,1,88,72,12,12,0,0,1,100,84Z"/>',
|
|
52
|
+
"youtube-logo" => '<path d="M164.44,121.34l-48-32A8,8,0,0,0,104,96v64a8,8,0,0,0,12.44,6.66l48-32a8,8,0,0,0,0-13.32ZM120,145.05V111l25.58,17ZM234.33,69.52a24,24,0,0,0-14.49-16.4C185.56,39.88,131,40,128,40s-57.56-.12-91.84,13.12a24,24,0,0,0-14.49,16.4C19.08,79.5,16,97.74,16,128s3.08,48.5,5.67,58.48a24,24,0,0,0,14.49,16.41C69,215.56,120.4,216,127.34,216h1.32c6.94,0,58.37-.44,91.18-13.11a24,24,0,0,0,14.49-16.41c2.59-10,5.67-28.22,5.67-58.48S236.92,79.5,234.33,69.52Zm-15.49,113a8,8,0,0,1-4.77,5.49c-31.65,12.22-85.48,12-86,12H128c-.54,0-54.33.2-86-12a8,8,0,0,1-4.77-5.49C34.8,173.39,32,156.57,32,128s2.8-45.39,5.16-54.47A8,8,0,0,1,41.93,68c30.52-11.79,81.66-12,85.85-12h.27c.54,0,54.38-.18,86,12a8,8,0,0,1,4.77,5.49C221.2,82.61,224,99.43,224,128S221.2,173.39,218.84,182.47Z"/>',
|
|
53
|
+
"twitter-logo" => '<path d="M214.75,211.71l-62.6-98.38,61.77-67.95a8,8,0,0,0-11.84-10.76L143.24,99.34,102.75,35.71A8,8,0,0,0,96,32H48a8,8,0,0,0-6.75,12.3l62.6,98.37-61.77,68a8,8,0,1,0,11.84,10.76l58.84-64.72,40.49,63.63A8,8,0,0,0,160,224h48a8,8,0,0,0,6.75-12.29ZM164.39,208,62.57,48h29L193.43,208Z"/>',
|
|
54
|
+
"instagram-logo" => '<path d="M128,80a48,48,0,1,0,48,48A48.05,48.05,0,0,0,128,80Zm0,80a32,32,0,1,1,32-32A32,32,0,0,1,128,160ZM176,24H80A56.06,56.06,0,0,0,24,80v96a56.06,56.06,0,0,0,56,56h96a56.06,56.06,0,0,0,56-56V80A56.06,56.06,0,0,0,176,24Zm40,152a40,40,0,0,1-40,40H80a40,40,0,0,1-40-40V80A40,40,0,0,1,80,40h96a40,40,0,0,1,40,40ZM192,76a12,12,0,1,1-12-12A12,12,0,0,1,192,76Z"/>',
|
|
55
|
+
"facebook-logo" => '<path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm8,191.63V152h24a8,8,0,0,0,0-16H136V112a16,16,0,0,1,16-16h16a8,8,0,0,0,0-16H152a32,32,0,0,0-32,32v24H96a8,8,0,0,0,0,16h24v63.63a88,88,0,1,1,16,0Z"/>',
|
|
56
|
+
"tiktok-logo" => '<path d="M224,72a48.05,48.05,0,0,1-48-48,8,8,0,0,0-8-8H128a8,8,0,0,0-8,8V156a20,20,0,1,1-28.57-18.08A8,8,0,0,0,96,130.69V88a8,8,0,0,0-9.4-7.88C50.91,86.48,24,119.1,24,156a76,76,0,0,0,152,0V116.29A103.25,103.25,0,0,0,224,128a8,8,0,0,0,8-8V80A8,8,0,0,0,224,72Zm-8,39.64a87.19,87.19,0,0,1-43.33-16.15A8,8,0,0,0,160,102v54a60,60,0,0,1-120,0c0-25.9,16.64-49.13,40-57.6v27.67A36,36,0,1,0,136,156V32h24.5A64.14,64.14,0,0,0,216,87.5Z"/>',
|
|
57
|
+
"twitch-logo" => '<path d="M208,32H48A16,16,0,0,0,32,48V192a16,16,0,0,0,16,16H64v32a8,8,0,0,0,13.12,6.15L122.9,208h42.2a16,16,0,0,0,10.25-3.71l42.89-35.75A15.93,15.93,0,0,0,224,156.25V48A16,16,0,0,0,208,32Zm0,124.25L165.1,192H120a8,8,0,0,0-5.12,1.85L80,222.92V200a8,8,0,0,0-8-8H48V48H208ZM160,136V88a8,8,0,0,1,16,0v48a8,8,0,0,1-16,0Zm-48,0V88a8,8,0,0,1,16,0v48a8,8,0,0,1-16,0Z"/>',
|
|
58
|
+
"reddit-logo" => '<path d="M248,104a32,32,0,0,0-52.94-24.19c-16.75-8.9-36.76-14.28-57.66-15.53l5.19-31.17,17.72,2.72a24,24,0,1,0,2.87-15.74l-26-4a8,8,0,0,0-9.11,6.59L121.2,64.16c-21.84.94-42.82,6.38-60.26,15.65a32,32,0,0,0-42.59,47.74A59,59,0,0,0,16,144c0,21.93,12,42.35,33.91,57.49C70.88,216,98.61,224,128,224s57.12-8,78.09-22.51C228,186.35,240,165.93,240,144a59,59,0,0,0-2.35-16.45A32.16,32.16,0,0,0,248,104ZM184,24a8,8,0,1,1-8,8A8,8,0,0,1,184,24Zm40.13,93.78a8,8,0,0,0-3.29,10A43.58,43.58,0,0,1,224,144c0,16.53-9.59,32.27-27,44.33C178.67,201,154.17,208,128,208s-50.67-7-69-19.67C41.59,176.27,32,160.53,32,144a43.75,43.75,0,0,1,3.14-16.17,8,8,0,0,0-3.27-10A16,16,0,1,1,52.94,94.59a8,8,0,0,0,10.45,2.23l.36-.22C81.45,85.9,104.25,80,128,80h0c23.73,0,46.53,5.9,64.23,16.6l.42.25a8,8,0,0,0,10.39-2.26,16,16,0,1,1,21.07,23.19ZM88,144a16,16,0,1,1,16-16A16,16,0,0,1,88,144Zm96-16a16,16,0,1,1-16-16A16,16,0,0,1,184,128Zm-16.93,44.25a8,8,0,0,1-3.32,10.82,76.18,76.18,0,0,1-71.5,0,8,8,0,1,1,7.5-14.14,60.18,60.18,0,0,0,56.5,0A8,8,0,0,1,167.07,172.25Z"/>',
|
|
59
|
+
"mastodon-logo" => '<path d="M184,32H72A40,40,0,0,0,32,72V192a40,40,0,0,0,40,40h88a8,8,0,0,0,0-16H72a24,24,0,0,1-24-24v-8H184a40,40,0,0,0,40-40V72A40,40,0,0,0,184,32Zm24,112a24,24,0,0,1-24,24H48V72A24,24,0,0,1,72,48H184a24,24,0,0,1,24,24Zm-24-40v32a8,8,0,0,1-16,0V104a16,16,0,0,0-32,0v32a8,8,0,0,1-16,0V104a16,16,0,0,0-32,0v32a8,8,0,0,1-16,0V104a32,32,0,0,1,56-21.13A32,32,0,0,1,184,104Z"/>',
|
|
60
|
+
"threads-logo" => '<path d="M186.42,123.65a63.81,63.81,0,0,0-11.13-6.72c-4-29.89-24-39.31-33.1-42.07-19.78-6-42.51,1.19-52.85,16.7a8,8,0,0,0,13.32,8.88c6.37-9.56,22-14.16,34.89-10.27,9.95,3,16.82,10.3,20.15,21a81.05,81.05,0,0,0-15.29-1.43c-13.92,0-26.95,3.59-36.67,10.1C94.3,127.57,88,139,88,152c0,20.58,15.86,35.52,37.71,35.52a48,48,0,0,0,34.35-14.81c6.44-6.7,14-18.36,15.61-37.1.38.26.74.53,1.1.8C186.88,144.05,192,154.68,192,168c0,19.36-20.34,48-64,48-26.73,0-45.48-8.65-57.34-26.44C60.93,175,56,154.26,56,128s4.93-47,14.66-61.56C82.52,48.65,101.27,40,128,40c32.93,0,54,13.25,64.53,40.52a8,8,0,1,0,14.93-5.75C194.68,41.56,167.2,24,128,24,96,24,72.19,35.29,57.34,57.56,45.83,74.83,40,98.52,40,128s5.83,53.17,17.34,70.44C72.19,220.71,96,232,128,232c30.07,0,48.9-11.48,59.4-21.1C200.3,199.08,208,183,208,168,208,149.66,200.54,134.32,186.42,123.65Zm-37.89,38a31.94,31.94,0,0,1-22.82,9.9c-10.81,0-21.71-6-21.71-19.52,0-12.63,12-26.21,38.41-26.21A63.88,63.88,0,0,1,160,128.24C160,142.32,156,153.86,148.53,161.62Z"/>',
|
|
61
|
+
"pinterest-logo" => '<path d="M224,112c0,22.57-7.9,43.2-22.23,58.11C188.39,184,170.25,192,152,192c-17.88,0-29.82-5.86-37.43-12l-10.78,45.82A8,8,0,0,1,96,232a8.24,8.24,0,0,1-1.84-.21,8,8,0,0,1-6-9.62l32-136a8,8,0,0,1,15.58,3.66l-16.9,71.8C122,166,131.3,176,152,176c27.53,0,56-23.94,56-64A72,72,0,1,0,73.63,148a8,8,0,0,1-13.85,8A88,88,0,1,1,224,112Z"/>',
|
|
62
|
+
"medium-logo" => '<path d="M72,64a64,64,0,1,0,64,64A64.07,64.07,0,0,0,72,64Zm0,112a48,48,0,1,1,48-48A48.05,48.05,0,0,1,72,176ZM184,64c-5.68,0-16.4,2.76-24.32,21.25C154.73,96.8,152,112,152,128s2.73,31.2,7.68,42.75C167.6,189.24,178.32,192,184,192s16.4-2.76,24.32-21.25C213.27,159.2,216,144,216,128s-2.73-31.2-7.68-42.75C200.4,66.76,189.68,64,184,64Zm0,112c-5.64,0-16-18.22-16-48s10.36-48,16-48,16,18.22,16,48S189.64,176,184,176ZM248,72V184a8,8,0,0,1-16,0V72a8,8,0,0,1,16,0Z"/>',
|
|
63
|
+
"slack-logo" => '<path d="M221.13,128A32,32,0,0,0,184,76.31V56a32,32,0,0,0-56-21.13A32,32,0,0,0,76.31,72H56a32,32,0,0,0-21.13,56A32,32,0,0,0,72,179.69V200a32,32,0,0,0,56,21.13A32,32,0,0,0,179.69,184H200a32,32,0,0,0,21.13-56ZM72,152a16,16,0,1,1-16-16H72Zm48,48a16,16,0,0,1-32,0V152a16,16,0,0,1,16-16h16Zm0-80H56a16,16,0,0,1,0-32h48a16,16,0,0,1,16,16Zm0-48H104a16,16,0,1,1,16-16Zm16-16a16,16,0,0,1,32,0v48a16,16,0,0,1-16,16H136Zm16,160a16,16,0,0,1-16-16V184h16a16,16,0,0,1,0,32Zm48-48H152a16,16,0,0,1-16-16V136h64a16,16,0,0,1,0,32Zm0-48H184V104a16,16,0,1,1,16,16Z"/>',
|
|
64
|
+
"gitlab-logo" => '<path d="M230.15,117.1,210.25,41a11.94,11.94,0,0,0-22.79-1.11L169.78,88H86.22L68.54,39.87A11.94,11.94,0,0,0,45.75,41L25.85,117.1a57.19,57.19,0,0,0,22,61l73.27,51.76a11.91,11.91,0,0,0,13.74,0l73.27-51.76A57.19,57.19,0,0,0,230.15,117.1ZM58,57.5,73.13,98.76A8,8,0,0,0,80.64,104h94.72a8,8,0,0,0,7.51-5.24L198,57.5l13.07,50L128,166.21,44.9,107.5ZM40.68,124.11,114.13,176,93.41,190.65,57.09,165A41.06,41.06,0,0,1,40.68,124.11Zm87.32,91-20.73-14.65L128,185.8l20.73,14.64ZM198.91,165l-36.32,25.66L141.87,176l73.45-51.9A41.06,41.06,0,0,1,198.91,165Z"/>'
|
|
40
65
|
},
|
|
41
66
|
"bold" => {
|
|
42
67
|
"heart" => '<path d="M178,36c-20.09,0-37.92,7.93-50,21.56C115.92,43.93,98.09,36,78,36a66.08,66.08,0,0,0-66,66c0,72.34,105.81,130.14,110.31,132.57a12,12,0,0,0,11.38,0C138.19,232.14,244,174.34,244,102A66.08,66.08,0,0,0,178,36Zm-5.49,142.36A328.69,328.69,0,0,1,128,210.16a328.69,328.69,0,0,1-44.51-31.8C61.82,159.77,36,131.42,36,102A42,42,0,0,1,78,60c17.8,0,32.7,9.4,38.89,24.54a12,12,0,0,0,22.22,0C145.3,69.4,160.2,60,178,60a42,42,0,0,1,42,42C220,131.42,194.18,159.77,172.51,178.36Z"/>'
|
|
@@ -3,19 +3,20 @@
|
|
|
3
3
|
require "kramdown"
|
|
4
4
|
require "kramdown-parser-gfm"
|
|
5
5
|
require "yaml"
|
|
6
|
-
require_relative "components/registry"
|
|
7
|
-
require_relative "components/base_processor"
|
|
8
|
-
require_relative "components/callout_processor"
|
|
9
|
-
require_relative "components/tabs_processor"
|
|
10
|
-
require_relative "components/icon_processor"
|
|
11
|
-
require_relative "components/code_block_processor"
|
|
12
|
-
require_relative "components/code_snippet_import_preprocessor"
|
|
13
|
-
require_relative "components/code_block_options_preprocessor"
|
|
14
|
-
require_relative "components/code_block_diff_preprocessor"
|
|
15
|
-
require_relative "components/code_block_focus_preprocessor"
|
|
16
|
-
require_relative "components/table_wrapper_processor"
|
|
17
|
-
require_relative "components/heading_anchor_processor"
|
|
18
|
-
require_relative "components/table_of_contents_processor"
|
|
6
|
+
require_relative "../components/registry"
|
|
7
|
+
require_relative "../components/base_processor"
|
|
8
|
+
require_relative "../components/processors/callout_processor"
|
|
9
|
+
require_relative "../components/processors/tabs_processor"
|
|
10
|
+
require_relative "../components/processors/icon_processor"
|
|
11
|
+
require_relative "../components/processors/code_block_processor"
|
|
12
|
+
require_relative "../components/processors/code_snippet_import_preprocessor"
|
|
13
|
+
require_relative "../components/processors/code_block_options_preprocessor"
|
|
14
|
+
require_relative "../components/processors/code_block_diff_preprocessor"
|
|
15
|
+
require_relative "../components/processors/code_block_focus_preprocessor"
|
|
16
|
+
require_relative "../components/processors/table_wrapper_processor"
|
|
17
|
+
require_relative "../components/processors/heading_anchor_processor"
|
|
18
|
+
require_relative "../components/processors/table_of_contents_processor"
|
|
19
|
+
require_relative "../components/aliases"
|
|
19
20
|
|
|
20
21
|
module Docyard
|
|
21
22
|
class Markdown
|
|
@@ -61,6 +62,10 @@ module Docyard
|
|
|
61
62
|
frontmatter.dig("sidebar", "collapsed")
|
|
62
63
|
end
|
|
63
64
|
|
|
65
|
+
def sidebar_order
|
|
66
|
+
frontmatter.dig("sidebar", "order")
|
|
67
|
+
end
|
|
68
|
+
|
|
64
69
|
def toc
|
|
65
70
|
@context[:toc] || []
|
|
66
71
|
end
|
|
@@ -90,6 +95,7 @@ module Docyard
|
|
|
90
95
|
input: "GFM",
|
|
91
96
|
hard_wrap: false,
|
|
92
97
|
syntax_highlighter: "rouge",
|
|
98
|
+
syntax_highlighter_opts: { guess_lang: true },
|
|
93
99
|
parse_block_html: true
|
|
94
100
|
).to_html
|
|
95
101
|
|