docyard 0.7.0 → 0.9.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.
Files changed (155) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +5 -1
  3. data/CHANGELOG.md +43 -1
  4. data/lib/docyard/build/asset_bundler.rb +22 -7
  5. data/lib/docyard/build/file_copier.rb +49 -27
  6. data/lib/docyard/build/sitemap_generator.rb +6 -6
  7. data/lib/docyard/build/static_generator.rb +85 -12
  8. data/lib/docyard/builder.rb +6 -6
  9. data/lib/docyard/components/aliases.rb +12 -0
  10. data/lib/docyard/components/processors/abbreviation_processor.rb +72 -0
  11. data/lib/docyard/components/processors/accordion_processor.rb +81 -0
  12. data/lib/docyard/components/processors/badge_processor.rb +72 -0
  13. data/lib/docyard/components/processors/callout_processor.rb +8 -2
  14. data/lib/docyard/components/processors/cards_processor.rb +100 -0
  15. data/lib/docyard/components/processors/code_block_options_preprocessor.rb +23 -2
  16. data/lib/docyard/components/processors/code_block_processor.rb +6 -0
  17. data/lib/docyard/components/processors/code_group_processor.rb +198 -0
  18. data/lib/docyard/components/processors/code_snippet_import_preprocessor.rb +6 -1
  19. data/lib/docyard/components/processors/custom_anchor_processor.rb +42 -0
  20. data/lib/docyard/components/processors/file_tree_processor.rb +151 -0
  21. data/lib/docyard/components/processors/image_caption_processor.rb +96 -0
  22. data/lib/docyard/components/processors/include_processor.rb +86 -0
  23. data/lib/docyard/components/processors/steps_processor.rb +89 -0
  24. data/lib/docyard/components/processors/tabs_processor.rb +9 -1
  25. data/lib/docyard/components/processors/tooltip_processor.rb +57 -0
  26. data/lib/docyard/components/processors/video_embed_processor.rb +196 -0
  27. data/lib/docyard/components/support/code_group/html_builder.rb +122 -0
  28. data/lib/docyard/components/support/markdown_code_block_helper.rb +56 -0
  29. data/lib/docyard/config/branding_resolver.rb +121 -17
  30. data/lib/docyard/config/constants.rb +6 -4
  31. data/lib/docyard/config/logo_detector.rb +39 -0
  32. data/lib/docyard/config/validator.rb +122 -99
  33. data/lib/docyard/config.rb +40 -42
  34. data/lib/docyard/initializer.rb +15 -76
  35. data/lib/docyard/navigation/breadcrumb_builder.rb +133 -0
  36. data/lib/docyard/navigation/prev_next_builder.rb +4 -1
  37. data/lib/docyard/navigation/sidebar/children_discoverer.rb +51 -0
  38. data/lib/docyard/navigation/sidebar/config_parser.rb +136 -108
  39. data/lib/docyard/navigation/sidebar/file_resolver.rb +90 -0
  40. data/lib/docyard/navigation/sidebar/file_system_scanner.rb +2 -1
  41. data/lib/docyard/navigation/sidebar/item.rb +50 -7
  42. data/lib/docyard/navigation/sidebar/local_config_loader.rb +51 -0
  43. data/lib/docyard/navigation/sidebar/metadata_extractor.rb +71 -0
  44. data/lib/docyard/navigation/sidebar/metadata_reader.rb +51 -0
  45. data/lib/docyard/navigation/sidebar/path_prefixer.rb +34 -0
  46. data/lib/docyard/navigation/sidebar/renderer.rb +60 -38
  47. data/lib/docyard/navigation/sidebar/sorter.rb +21 -0
  48. data/lib/docyard/navigation/sidebar/tree_builder.rb +100 -26
  49. data/lib/docyard/navigation/sidebar/tree_filter.rb +55 -0
  50. data/lib/docyard/navigation/sidebar_builder.rb +105 -36
  51. data/lib/docyard/rendering/icon_helpers.rb +13 -0
  52. data/lib/docyard/rendering/icons/phosphor.rb +26 -1
  53. data/lib/docyard/rendering/markdown.rb +29 -1
  54. data/lib/docyard/rendering/renderer.rb +75 -34
  55. data/lib/docyard/rendering/template_resolver.rb +172 -0
  56. data/lib/docyard/routing/fallback_resolver.rb +92 -0
  57. data/lib/docyard/search/build_indexer.rb +1 -1
  58. data/lib/docyard/search/dev_indexer.rb +51 -6
  59. data/lib/docyard/search/pagefind_support.rb +2 -0
  60. data/lib/docyard/server/asset_handler.rb +25 -19
  61. data/lib/docyard/server/pagefind_handler.rb +63 -0
  62. data/lib/docyard/server/preview_server.rb +1 -1
  63. data/lib/docyard/server/rack_application.rb +81 -64
  64. data/lib/docyard/templates/assets/css/code.css +18 -51
  65. data/lib/docyard/templates/assets/css/components/abbreviation.css +86 -0
  66. data/lib/docyard/templates/assets/css/components/accordion.css +138 -0
  67. data/lib/docyard/templates/assets/css/components/badges.css +47 -0
  68. data/lib/docyard/templates/assets/css/components/banner.css +202 -0
  69. data/lib/docyard/templates/assets/css/components/breadcrumbs.css +143 -0
  70. data/lib/docyard/templates/assets/css/components/callout.css +67 -67
  71. data/lib/docyard/templates/assets/css/components/cards.css +100 -0
  72. data/lib/docyard/templates/assets/css/components/code-block.css +190 -282
  73. data/lib/docyard/templates/assets/css/components/code-group.css +281 -0
  74. data/lib/docyard/templates/assets/css/components/figure.css +22 -0
  75. data/lib/docyard/templates/assets/css/components/file-tree.css +124 -0
  76. data/lib/docyard/templates/assets/css/components/heading-anchor.css +36 -15
  77. data/lib/docyard/templates/assets/css/components/icon.css +0 -1
  78. data/lib/docyard/templates/assets/css/components/lightbox.css +65 -0
  79. data/lib/docyard/templates/assets/css/components/logo.css +0 -2
  80. data/lib/docyard/templates/assets/css/components/nav-menu.css +237 -0
  81. data/lib/docyard/templates/assets/css/components/navigation.css +193 -167
  82. data/lib/docyard/templates/assets/css/components/prev-next.css +68 -48
  83. data/lib/docyard/templates/assets/css/components/search.css +186 -174
  84. data/lib/docyard/templates/assets/css/components/steps.css +122 -0
  85. data/lib/docyard/templates/assets/css/components/tab-bar.css +163 -0
  86. data/lib/docyard/templates/assets/css/components/table-of-contents.css +127 -114
  87. data/lib/docyard/templates/assets/css/components/tabs.css +119 -160
  88. data/lib/docyard/templates/assets/css/components/theme-toggle.css +48 -44
  89. data/lib/docyard/templates/assets/css/components/tooltip.css +113 -0
  90. data/lib/docyard/templates/assets/css/components/video.css +41 -0
  91. data/lib/docyard/templates/assets/css/landing.css +815 -0
  92. data/lib/docyard/templates/assets/css/layout.css +489 -87
  93. data/lib/docyard/templates/assets/css/main.css +1 -3
  94. data/lib/docyard/templates/assets/css/markdown.css +113 -93
  95. data/lib/docyard/templates/assets/css/reset.css +0 -3
  96. data/lib/docyard/templates/assets/css/typography.css +43 -41
  97. data/lib/docyard/templates/assets/css/variables.css +268 -208
  98. data/lib/docyard/templates/assets/favicon.svg +7 -8
  99. data/lib/docyard/templates/assets/fonts/Inter-Variable.ttf +0 -0
  100. data/lib/docyard/templates/assets/js/components/abbreviation.js +85 -0
  101. data/lib/docyard/templates/assets/js/components/banner.js +81 -0
  102. data/lib/docyard/templates/assets/js/components/code-block.js +24 -42
  103. data/lib/docyard/templates/assets/js/components/code-group.js +283 -0
  104. data/lib/docyard/templates/assets/js/components/file-tree.js +39 -0
  105. data/lib/docyard/templates/assets/js/components/heading-anchor.js +26 -24
  106. data/lib/docyard/templates/assets/js/components/lightbox.js +72 -0
  107. data/lib/docyard/templates/assets/js/components/navigation.js +181 -70
  108. data/lib/docyard/templates/assets/js/components/search.js +0 -75
  109. data/lib/docyard/templates/assets/js/components/sidebar-toggle.js +29 -0
  110. data/lib/docyard/templates/assets/js/components/tab-navigation.js +145 -0
  111. data/lib/docyard/templates/assets/js/components/table-of-contents.js +153 -66
  112. data/lib/docyard/templates/assets/js/components/tabs.js +31 -69
  113. data/lib/docyard/templates/assets/js/components/tooltip.js +118 -0
  114. data/lib/docyard/templates/assets/js/theme.js +0 -3
  115. data/lib/docyard/templates/assets/logo-dark.svg +8 -2
  116. data/lib/docyard/templates/assets/logo.svg +7 -4
  117. data/lib/docyard/templates/config/docyard.yml.erb +37 -34
  118. data/lib/docyard/templates/errors/404.html.erb +1 -1
  119. data/lib/docyard/templates/errors/500.html.erb +1 -1
  120. data/lib/docyard/templates/layouts/default.html.erb +19 -67
  121. data/lib/docyard/templates/layouts/splash.html.erb +177 -0
  122. data/lib/docyard/templates/partials/_accordion.html.erb +9 -0
  123. data/lib/docyard/templates/partials/_banner.html.erb +27 -0
  124. data/lib/docyard/templates/partials/_breadcrumbs.html.erb +24 -0
  125. data/lib/docyard/templates/partials/_card.html.erb +23 -0
  126. data/lib/docyard/templates/partials/_code_block.html.erb +5 -3
  127. data/lib/docyard/templates/partials/_doc_footer.html.erb +25 -0
  128. data/lib/docyard/templates/partials/_features.html.erb +15 -0
  129. data/lib/docyard/templates/partials/_footer.html.erb +42 -0
  130. data/lib/docyard/templates/partials/_head.html.erb +22 -0
  131. data/lib/docyard/templates/partials/_header.html.erb +49 -0
  132. data/lib/docyard/templates/partials/_heading_anchor.html.erb +3 -1
  133. data/lib/docyard/templates/partials/_hero.html.erb +27 -0
  134. data/lib/docyard/templates/partials/_nav_group.html.erb +31 -11
  135. data/lib/docyard/templates/partials/_nav_leaf.html.erb +4 -1
  136. data/lib/docyard/templates/partials/_nav_menu.html.erb +42 -0
  137. data/lib/docyard/templates/partials/_nav_nested_section.html.erb +11 -0
  138. data/lib/docyard/templates/partials/_nav_section.html.erb +1 -1
  139. data/lib/docyard/templates/partials/_prev_next.html.erb +8 -2
  140. data/lib/docyard/templates/partials/_scripts.html.erb +7 -0
  141. data/lib/docyard/templates/partials/_search_modal.html.erb +2 -6
  142. data/lib/docyard/templates/partials/_search_trigger.html.erb +2 -6
  143. data/lib/docyard/templates/partials/_sidebar.html.erb +21 -4
  144. data/lib/docyard/templates/partials/_step.html.erb +14 -0
  145. data/lib/docyard/templates/partials/_tab_bar.html.erb +25 -0
  146. data/lib/docyard/templates/partials/_table_of_contents.html.erb +12 -12
  147. data/lib/docyard/templates/partials/_table_of_contents_toggle.html.erb +1 -3
  148. data/lib/docyard/templates/partials/_tabs.html.erb +2 -2
  149. data/lib/docyard/templates/partials/_theme_toggle.html.erb +2 -11
  150. data/lib/docyard/version.rb +1 -1
  151. metadata +70 -5
  152. data/lib/docyard/templates/markdown/getting-started/installation.md.erb +0 -77
  153. data/lib/docyard/templates/markdown/guides/configuration.md.erb +0 -202
  154. data/lib/docyard/templates/markdown/guides/markdown-features.md.erb +0 -247
  155. data/lib/docyard/templates/markdown/index.md.erb +0 -82
@@ -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
@@ -5,19 +5,23 @@ require_relative "sidebar/title_extractor"
5
5
  require_relative "sidebar/tree_builder"
6
6
  require_relative "sidebar/renderer"
7
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"
8
11
 
9
12
  module Docyard
10
13
  class SidebarBuilder
11
- attr_reader :docs_path, :current_path, :config
14
+ attr_reader :docs_path, :current_path, :config, :header_ctas
12
15
 
13
- def initialize(docs_path:, current_path: "/", config: nil)
16
+ def initialize(docs_path:, current_path: "/", config: nil, header_ctas: [])
14
17
  @docs_path = docs_path
15
18
  @current_path = current_path
16
19
  @config = config
20
+ @header_ctas = header_ctas
17
21
  end
18
22
 
19
23
  def tree
20
- @tree ||= build_tree
24
+ @tree ||= build_scoped_tree
21
25
  end
22
26
 
23
27
  def to_html
@@ -26,65 +30,130 @@ module Docyard
26
30
 
27
31
  private
28
32
 
29
- def build_tree
30
- if config_sidebar_items?
31
- build_tree_from_config
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)
32
60
  else
33
- build_tree_from_filesystem
61
+ Sidebar::TreeFilter.new(build_tree_for_path(docs_path), tab_path).filter
34
62
  end
35
63
  end
36
64
 
37
- def build_tree_from_config
38
- config_parser.parse.map(&:to_h)
65
+ def scoped_sidebar_available?(path)
66
+ File.directory?(path) && Sidebar::LocalConfigLoader.new(path).config_file_exists?
39
67
  end
40
68
 
41
- def build_tree_from_filesystem
42
- file_items = scanner.scan
43
- tree_builder.build(file_items)
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)
44
73
  end
45
74
 
46
- def config_sidebar_items?
47
- config_sidebar_items&.any?
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
48
81
  end
49
82
 
50
- def config_sidebar_items
51
- return [] unless config
83
+ def maybe_prepend_overview(tree, path, base_url_prefix)
84
+ return tree if skip_overview?(tree, path, base_url_prefix)
52
85
 
53
- config.sidebar&.items || []
86
+ [build_overview_item(base_url_prefix)] + tree
54
87
  end
55
88
 
56
- def config_parser
57
- @config_parser ||= Sidebar::ConfigParser.new(
58
- config_sidebar_items,
59
- docs_path: docs_path,
60
- current_path: current_path
61
- )
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 }
62
94
  end
63
95
 
64
- def scanner
65
- @scanner ||= Sidebar::FileSystemScanner.new(docs_path)
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
+ }
66
103
  end
67
104
 
68
- def tree_builder
69
- @tree_builder ||= Sidebar::TreeBuilder.new(
70
- docs_path: docs_path,
71
- current_path: current_path
72
- )
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
73
128
  end
74
129
 
75
130
  def renderer
76
131
  @renderer ||= Sidebar::Renderer.new(
77
- site_title: extract_site_title,
78
- base_url: extract_base_url
132
+ site_title: config&.title || "Documentation",
133
+ base_url: config&.build&.base || "/",
134
+ header_ctas: header_ctas
79
135
  )
80
136
  end
81
137
 
82
- def extract_base_url
83
- config&.build&.base_url || "/"
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) }
84
148
  end
85
149
 
86
- def extract_site_title
87
- config&.site&.title || "Documentation"
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}/")
88
157
  end
89
158
  end
90
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
@@ -8,6 +8,9 @@ module Docyard
8
8
  # Licensed under MIT License (see LICENSE.phosphor)
9
9
  PHOSPHOR = {
10
10
  "regular" => {
11
+ "folder" => '<path d="M216,72H131.31L104,44.69A15.86,15.86,0,0,0,92.69,40H40A16,16,0,0,0,24,56V200.62A15.4,15.4,0,0,0,39.38,216H216.89A15.13,15.13,0,0,0,232,200.89V88A16,16,0,0,0,216,72ZM40,56H92.69l16,16H40ZM216,200H40V88H216Z"/>',
12
+ "folder-open" => '<path d="M245,110.64A16,16,0,0,0,232,104H216V88a16,16,0,0,0-16-16H130.67L102.94,51.2a16.14,16.14,0,0,0-9.6-3.2H40A16,16,0,0,0,24,64V208h0a8,8,0,0,0,8,8H211.1a8,8,0,0,0,7.59-5.47l28.49-85.47A16.05,16.05,0,0,0,245,110.64ZM93.34,64,123.2,86.4A8,8,0,0,0,128,88h72v16H69.77a16,16,0,0,0-15.18,10.94L40,158.7V64Zm112,136H43.1l26.67-80H232Z"/>',
13
+ "file-text" => '<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,8h48V216Zm-32-80a8,8,0,0,1-8,8H96a8,8,0,0,1,0-16h64A8,8,0,0,1,168,136Zm0,32a8,8,0,0,1-8,8H96a8,8,0,0,1,0-16h64A8,8,0,0,1,168,168Z"/>',
11
14
  "heart" => '<path d="M178,40c-20.65,0-38.73,8.88-50,23.89C116.73,48.88,98.65,40,78,40a62.07,62.07,0,0,0-62,62c0,70,103.79,126.66,108.21,129a8,8,0,0,0,7.58,0C136.21,228.66,240,172,240,102A62.07,62.07,0,0,0,178,40ZM128,214.8C109.74,204.16,32,155.69,32,102A46.06,46.06,0,0,1,78,56c19.45,0,35.78,10.36,42.6,27a8,8,0,0,0,14.8,0c6.82-16.67,23.15-27,42.6-27a46.06,46.06,0,0,1,46,46C224,155.61,146.24,204.15,128,214.8Z"/>',
12
15
  "arrow-right" => '<path d="M221.66,133.66l-72,72a8,8,0,0,1-11.32-11.32L196.69,136H40a8,8,0,0,1,0-16H196.69L138.34,61.66a8,8,0,0,1,11.32-11.32l72,72A8,8,0,0,1,221.66,133.66Z"/>',
13
16
  "arrow-left" => '<path d="M224,128a8,8,0,0,1-8,8H59.31l58.35,58.34a8,8,0,0,1-11.32,11.32l-72-72a8,8,0,0,1,0-11.32l72-72a8,8,0,0,1,11.32,11.32L59.31,120H216A8,8,0,0,1,224,128Z"/>',
@@ -39,7 +42,29 @@ module Docyard
39
42
  "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
43
  "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
44
  "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"/>'
45
+ "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"/>',
46
+ "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"/>',
47
+ "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"/>',
48
+ "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"/>',
49
+ "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"/>',
50
+ "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"/>',
51
+ "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"/>',
52
+ "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"/>',
53
+ "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"/>',
54
+ "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"/>',
55
+ "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"/>',
56
+ "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"/>',
57
+ "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"/>',
58
+ "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"/>',
59
+ "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"/>',
60
+ "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"/>',
61
+ "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"/>',
62
+ "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"/>',
63
+ "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"/>',
64
+ "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"/>',
65
+ "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"/>',
66
+ "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"/>',
67
+ "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"/>'
43
68
  },
44
69
  "bold" => {
45
70
  "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"/>'
@@ -6,15 +6,27 @@ require "yaml"
6
6
  require_relative "../components/registry"
7
7
  require_relative "../components/base_processor"
8
8
  require_relative "../components/processors/callout_processor"
9
+ require_relative "../components/processors/accordion_processor"
10
+ require_relative "../components/processors/badge_processor"
11
+ require_relative "../components/processors/steps_processor"
12
+ require_relative "../components/processors/cards_processor"
9
13
  require_relative "../components/processors/tabs_processor"
14
+ require_relative "../components/processors/code_group_processor"
10
15
  require_relative "../components/processors/icon_processor"
11
16
  require_relative "../components/processors/code_block_processor"
12
17
  require_relative "../components/processors/code_snippet_import_preprocessor"
18
+ require_relative "../components/processors/include_processor"
13
19
  require_relative "../components/processors/code_block_options_preprocessor"
14
20
  require_relative "../components/processors/code_block_diff_preprocessor"
15
21
  require_relative "../components/processors/code_block_focus_preprocessor"
16
22
  require_relative "../components/processors/table_wrapper_processor"
17
23
  require_relative "../components/processors/heading_anchor_processor"
24
+ require_relative "../components/processors/custom_anchor_processor"
25
+ require_relative "../components/processors/image_caption_processor"
26
+ require_relative "../components/processors/video_embed_processor"
27
+ require_relative "../components/processors/file_tree_processor"
28
+ require_relative "../components/processors/abbreviation_processor"
29
+ require_relative "../components/processors/tooltip_processor"
18
30
  require_relative "../components/processors/table_of_contents_processor"
19
31
  require_relative "../components/aliases"
20
32
 
@@ -24,9 +36,10 @@ module Docyard
24
36
 
25
37
  attr_reader :raw, :config
26
38
 
27
- def initialize(raw, config: nil)
39
+ def initialize(raw, config: nil, file_path: nil)
28
40
  @raw = raw.freeze
29
41
  @config = config
42
+ @file_path = file_path
30
43
  @context = {}
31
44
  end
32
45
 
@@ -62,6 +75,18 @@ module Docyard
62
75
  frontmatter.dig("sidebar", "collapsed")
63
76
  end
64
77
 
78
+ def sidebar_order
79
+ frontmatter.dig("sidebar", "order")
80
+ end
81
+
82
+ def sidebar_badge
83
+ frontmatter.dig("sidebar", "badge")
84
+ end
85
+
86
+ def sidebar_badge_type
87
+ frontmatter.dig("sidebar", "badge_type")
88
+ end
89
+
65
90
  def toc
66
91
  @context[:toc] || []
67
92
  end
@@ -83,6 +108,8 @@ module Docyard
83
108
 
84
109
  def render_html
85
110
  @context[:config] = config&.data
111
+ @context[:current_file] = @file_path
112
+ @context[:docs_root] = "docs"
86
113
 
87
114
  preprocessed_content = Components::Registry.run_preprocessors(content, @context)
88
115
 
@@ -91,6 +118,7 @@ module Docyard
91
118
  input: "GFM",
92
119
  hard_wrap: false,
93
120
  syntax_highlighter: "rouge",
121
+ syntax_highlighter_opts: { guess_lang: true },
94
122
  parse_block_html: true
95
123
  ).to_html
96
124
 
@@ -2,51 +2,52 @@
2
2
 
3
3
  require "erb"
4
4
  require_relative "../config/constants"
5
+ require_relative "icon_helpers"
5
6
 
6
7
  module Docyard
7
8
  class Renderer
8
9
  include Utils::UrlHelpers
10
+ include IconHelpers
9
11
 
10
12
  LAYOUTS_PATH = File.join(__dir__, "../templates", "layouts")
11
13
  ERRORS_PATH = File.join(__dir__, "../templates", "errors")
12
14
  PARTIALS_PATH = File.join(__dir__, "../templates", "partials")
15
+ DEFAULT_LAYOUT = "default"
13
16
 
14
- attr_reader :layout_path, :base_url, :config
17
+ attr_reader :base_url, :config
15
18
 
16
- def initialize(layout: "default", base_url: "/", config: nil)
17
- @layout_path = File.join(LAYOUTS_PATH, "#{layout}.html.erb")
19
+ def initialize(base_url: "/", config: nil)
18
20
  @base_url = normalize_base_url(base_url)
19
21
  @config = config
20
22
  end
21
23
 
22
- def render_file(file_path, sidebar_html: "", prev_next_html: "", branding: {})
23
- markdown_content = File.read(file_path)
24
- markdown = Markdown.new(markdown_content, config: config)
25
-
26
- html_content = strip_md_from_links(markdown.html)
27
- toc = markdown.toc
24
+ def render_file(file_path, sidebar_html: "", prev_next_html: "", breadcrumbs: nil, branding: {},
25
+ template_options: {}, current_path: "/")
26
+ markdown = Markdown.new(File.read(file_path), config: config, file_path: file_path)
28
27
 
29
28
  render(
30
- content: html_content,
29
+ content: strip_md_from_links(markdown.html),
31
30
  page_title: markdown.title || Constants::DEFAULT_SITE_TITLE,
32
- navigation: {
33
- sidebar_html: sidebar_html,
34
- prev_next_html: prev_next_html,
35
- toc: toc
36
- },
37
- branding: branding
31
+ navigation: build_navigation(sidebar_html, prev_next_html, markdown.toc, breadcrumbs),
32
+ branding: branding,
33
+ template_options: template_options,
34
+ current_path: current_path
38
35
  )
39
36
  end
40
37
 
41
- def render(content:, page_title: Constants::DEFAULT_SITE_TITLE, navigation: {}, branding: {})
42
- template = File.read(layout_path)
38
+ def build_navigation(sidebar_html, prev_next_html, toc, breadcrumbs)
39
+ { sidebar_html: sidebar_html, prev_next_html: prev_next_html, toc: toc, breadcrumbs: breadcrumbs }
40
+ end
43
41
 
44
- sidebar_html = navigation[:sidebar_html] || ""
45
- prev_next_html = navigation[:prev_next_html] || ""
46
- toc = navigation[:toc] || []
42
+ def render(content:, page_title: Constants::DEFAULT_SITE_TITLE, navigation: {}, branding: {},
43
+ template_options: {}, current_path: "/")
44
+ layout = template_options[:template] || DEFAULT_LAYOUT
45
+ layout_path = File.join(LAYOUTS_PATH, "#{layout}.html.erb")
46
+ template = File.read(layout_path)
47
47
 
48
- assign_content_variables(content, page_title, sidebar_html, prev_next_html, toc)
49
- assign_branding_variables(branding)
48
+ assign_content_variables(content, page_title, navigation)
49
+ assign_branding_variables(branding, current_path)
50
+ assign_template_variables(template_options)
50
51
 
51
52
  ERB.new(template).result(binding)
52
53
  end
@@ -84,18 +85,20 @@ module Docyard
84
85
 
85
86
  private
86
87
 
87
- def assign_content_variables(content, page_title, sidebar_html, prev_next_html, toc)
88
+ def assign_content_variables(content, page_title, navigation)
88
89
  @content = content
89
90
  @page_title = page_title
90
- @sidebar_html = sidebar_html
91
- @prev_next_html = prev_next_html
92
- @toc = toc
91
+ @sidebar_html = navigation[:sidebar_html] || ""
92
+ @prev_next_html = navigation[:prev_next_html] || ""
93
+ @toc = navigation[:toc] || []
94
+ @breadcrumbs = navigation[:breadcrumbs]
93
95
  end
94
96
 
95
- def assign_branding_variables(branding)
97
+ def assign_branding_variables(branding, current_path = "/")
96
98
  assign_site_branding(branding)
97
- assign_display_options(branding)
98
99
  assign_search_options(branding)
100
+ assign_credits_and_social(branding)
101
+ assign_tabs(branding, current_path)
99
102
  end
100
103
 
101
104
  def assign_site_branding(branding)
@@ -104,11 +107,7 @@ module Docyard
104
107
  @logo = branding[:logo] || Constants::DEFAULT_LOGO_PATH
105
108
  @logo_dark = branding[:logo_dark]
106
109
  @favicon = branding[:favicon] || Constants::DEFAULT_FAVICON_PATH
107
- end
108
-
109
- def assign_display_options(branding)
110
- @display_logo = branding[:display_logo].nil? || branding[:display_logo]
111
- @display_title = branding[:display_title].nil? || branding[:display_title]
110
+ @has_custom_logo = branding[:has_custom_logo] || false
112
111
  end
113
112
 
114
113
  def assign_search_options(branding)
@@ -116,6 +115,48 @@ module Docyard
116
115
  @search_placeholder = branding[:search_placeholder] || "Search documentation..."
117
116
  end
118
117
 
118
+ def assign_credits_and_social(branding)
119
+ @credits = branding[:credits] != false
120
+ @copyright = branding[:copyright]
121
+ @social = branding[:social] || []
122
+ @header_ctas = branding[:header_ctas] || []
123
+ @announcement = branding[:announcement]
124
+ end
125
+
126
+ def assign_tabs(branding, current_path)
127
+ tabs = branding[:tabs] || []
128
+ @tabs = tabs.map { |tab| tab.merge(active: tab_active?(tab[:href], current_path)) }
129
+ @has_tabs = branding[:has_tabs] || false
130
+ @current_path = current_path
131
+ end
132
+
133
+ def tab_active?(tab_href, current_path)
134
+ return false if tab_href.nil? || current_path.nil?
135
+ return false if tab_href.start_with?("http://", "https://")
136
+
137
+ normalized_tab = tab_href.chomp("/")
138
+ normalized_current = current_path.chomp("/")
139
+
140
+ return true if normalized_tab == normalized_current
141
+
142
+ current_path.start_with?("#{normalized_tab}/")
143
+ end
144
+
145
+ def assign_template_variables(template_options)
146
+ @hero = template_options[:hero]
147
+ @features = template_options[:features]
148
+ @features_header = template_options[:features_header]
149
+ @show_sidebar = template_options.fetch(:show_sidebar, true)
150
+ @show_toc = template_options.fetch(:show_toc, true)
151
+ assign_footer_from_landing(template_options[:footer])
152
+ end
153
+
154
+ def assign_footer_from_landing(footer)
155
+ return unless footer
156
+
157
+ @footer_links = footer[:links]
158
+ end
159
+
119
160
  def strip_md_from_links(html)
120
161
  html.gsub(/href="([^"]+)\.md"/, 'href="\1"')
121
162
  end