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,177 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <%= render_partial('_head') %>
5
+ </head>
6
+ <body class="splash-page<%= ' has-sidebar' if @show_sidebar %><%= ' has-tabs' if @has_tabs %>">
7
+ <%= render_partial('_banner') %>
8
+ <a href="#main-content" class="skip-link">Skip to main content</a>
9
+
10
+ <%= render_partial('_header') %>
11
+ <%= render_partial('_tab_bar') %>
12
+ <%= render_partial('_nav_menu') %>
13
+
14
+ <% if @show_sidebar %>
15
+ <div class="secondary-header">
16
+ <button class="secondary-header-menu" aria-label="Toggle navigation menu" aria-expanded="false">
17
+ <%= icon(:sidebar) %>
18
+ <span>Menu</span>
19
+ </button>
20
+ </div>
21
+
22
+ <div class="mobile-overlay" aria-hidden="true"></div>
23
+
24
+ <div class="layout">
25
+ <%= @sidebar_html %>
26
+
27
+ <div class="layout-main">
28
+ <% end %>
29
+
30
+ <main id="main-content" class="splash-content">
31
+ <% if @hero %>
32
+ <%
33
+ hero_class = @hero[:image] ? 'hero hero--with-image' : 'hero hero--centered'
34
+ bg_style = @hero[:background] || 'grid'
35
+ %>
36
+ <section class="<%= hero_class %>">
37
+ <% if bg_style != 'none' %>
38
+ <div class="hero-bg hero-bg--<%= bg_style %>" aria-hidden="true">
39
+ <% if bg_style == 'glow' %>
40
+ <div class="hero-bg-orb hero-bg-orb--1"></div>
41
+ <div class="hero-bg-orb hero-bg-orb--2"></div>
42
+ <div class="hero-bg-orb hero-bg-orb--3"></div>
43
+ <% elsif bg_style == 'mesh' %>
44
+ <div class="hero-bg-mesh"></div>
45
+ <% end %>
46
+ </div>
47
+ <% end %>
48
+
49
+ <div class="hero-content">
50
+ <% if @hero[:badge] %>
51
+ <div class="hero-badge">
52
+ <span class="hero-badge-dot"></span>
53
+ <span class="hero-badge-text"><%= @hero[:badge] %></span>
54
+ </div>
55
+ <% end %>
56
+ <% if @hero[:title] %>
57
+ <%
58
+ title_class = @hero[:gradient] ? 'hero-title hero-title--gradient' : 'hero-title'
59
+ %>
60
+ <h1 class="<%= title_class %>"><%= @hero[:title] %></h1>
61
+ <% end %>
62
+ <% if @hero[:tagline] %>
63
+ <p class="hero-tagline"><%= @hero[:tagline] %></p>
64
+ <% end %>
65
+ <% if @hero[:actions]&.any? %>
66
+ <div class="hero-actions">
67
+ <% @hero[:actions].each do |action| %>
68
+ <%
69
+ is_external = action[:link]&.start_with?('http')
70
+ target_attr = action[:target] || (is_external ? '_blank' : nil)
71
+ rel_attr = action[:rel] || (is_external ? 'noopener noreferrer' : nil)
72
+ link_attrs = []
73
+ link_attrs << "target=\"#{target_attr}\"" if target_attr
74
+ link_attrs << "rel=\"#{rel_attr}\"" if rel_attr
75
+ %>
76
+ <a href="<%= link_path(action[:link]) %>" class="hero-action hero-action--<%= action[:variant] || 'primary' %>"<%= link_attrs.any? ? ' ' + link_attrs.join(' ') : '' %>>
77
+ <% if action[:icon] %>
78
+ <span class="hero-action-icon"><%= icon(action[:icon]) %></span>
79
+ <% end %>
80
+ <span><%= action[:text] %></span>
81
+ <% if action[:variant] != "secondary" %>
82
+ <svg class="hero-action-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14M12 5l7 7-7 7"/></svg>
83
+ <% end %>
84
+ </a>
85
+ <% end %>
86
+ </div>
87
+ <% end %>
88
+ </div>
89
+ <% if @hero[:image] %>
90
+ <div class="hero-image">
91
+ <% if @hero[:image][:light] || @hero[:image][:dark] %>
92
+ <% if @hero[:image][:light] %>
93
+ <img src="<%= asset_path(@hero[:image][:light]) %>" alt="<%= @hero[:image][:alt] || '' %>" loading="eager" class="hero-image-light">
94
+ <% end %>
95
+ <% if @hero[:image][:dark] %>
96
+ <img src="<%= asset_path(@hero[:image][:dark]) %>" alt="<%= @hero[:image][:alt] || '' %>" loading="eager" class="hero-image-dark">
97
+ <% end %>
98
+ <% else %>
99
+ <img src="<%= asset_path(@hero[:image][:src]) %>" alt="<%= @hero[:image][:alt] || '' %>" loading="eager">
100
+ <% end %>
101
+ </div>
102
+ <% end %>
103
+
104
+ </section>
105
+ <% end %>
106
+
107
+ <% if @features&.any? %>
108
+ <section class="features-section">
109
+ <% if @features_header %>
110
+ <div class="features-header">
111
+ <% if @features_header[:label] %>
112
+ <p class="features-label"><%= @features_header[:label] %></p>
113
+ <% end %>
114
+ <% if @features_header[:title] %>
115
+ <h2 class="features-title"><%= @features_header[:title] %></h2>
116
+ <% end %>
117
+ <% if @features_header[:description] %>
118
+ <p class="features-description"><%= @features_header[:description] %></p>
119
+ <% end %>
120
+ </div>
121
+ <% end %>
122
+
123
+ <div class="features-magazine">
124
+ <% @features.each_with_index do |feature, index| %>
125
+ <%
126
+ icon_color = feature[:color] || 'primary'
127
+ size_class = feature[:size] ? "feature-card--#{feature[:size]}" : ''
128
+ has_link = feature[:link] && !feature[:link].to_s.strip.empty?
129
+ tag = has_link ? 'a' : 'div'
130
+
131
+ feature_link_attrs = []
132
+ if has_link
133
+ feature_link_attrs << "href=\"#{link_path(feature[:link])}\""
134
+ is_external = feature[:link]&.start_with?('http')
135
+ target_attr = feature[:target] || (is_external ? '_blank' : nil)
136
+ rel_attr = feature[:rel] || (is_external ? 'noopener noreferrer' : nil)
137
+ feature_link_attrs << "target=\"#{target_attr}\"" if target_attr
138
+ feature_link_attrs << "rel=\"#{rel_attr}\"" if rel_attr
139
+ end
140
+ %>
141
+ <<%= tag %> <%= feature_link_attrs.join(' ') %> class="feature-card <%= size_class %>" style="--card-color: var(--feature-<%= icon_color %>)">
142
+ <% if feature[:icon] %>
143
+ <span class="feature-icon feature-icon--<%= icon_color %>"><%= icon(feature[:icon]) %></span>
144
+ <% end %>
145
+ <h3 class="feature-title"><%= feature[:title] %></h3>
146
+ <% if feature[:description] %>
147
+ <p class="feature-description"><%= feature[:description] %></p>
148
+ <% end %>
149
+ <% if has_link %>
150
+ <div class="feature-arrow">
151
+ <span><%= feature[:link_text] || 'Learn more' %></span>
152
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14M12 5l7 7-7 7"/></svg>
153
+ </div>
154
+ <% end %>
155
+ </<%= tag %>>
156
+ <% end %>
157
+ </div>
158
+ </section>
159
+ <% end %>
160
+
161
+ <% if @content && !@content.strip.empty? %>
162
+ <section class="splash-markdown">
163
+ <%= @content %>
164
+ </section>
165
+ <% end %>
166
+ </main>
167
+
168
+ <% if @show_sidebar %>
169
+ </div>
170
+ </div>
171
+ <% end %>
172
+
173
+ <%= render_partial('_footer') %>
174
+
175
+ <%= render_partial('_scripts') %>
176
+ </body>
177
+ </html>
@@ -0,0 +1,9 @@
1
+ <details class="docyard-accordion"<%= ' open' if @open %>>
2
+ <summary class="docyard-accordion__summary">
3
+ <span class="docyard-accordion__icon" aria-hidden="true"><%= @icon_svg %></span>
4
+ <span class="docyard-accordion__title"><%= @title %></span>
5
+ </summary>
6
+ <div class="docyard-accordion__content">
7
+ <%= @content_html %>
8
+ </div>
9
+ </details>
@@ -0,0 +1,27 @@
1
+ <% if @announcement %>
2
+ <div class="docyard-announcement" data-dismissible="<%= @announcement[:dismissible] %>"<%= @announcement[:button] ? ' data-has-button="true"' : '' %>>
3
+ <div class="docyard-announcement__content">
4
+ <% if @announcement[:link] %>
5
+ <a href="<%= @announcement[:link] %>" class="docyard-announcement__link">
6
+ <span class="docyard-announcement__text"><%= @announcement[:text] %></span>
7
+ <%= icon("arrow-right") %>
8
+ </a>
9
+ <% else %>
10
+ <span class="docyard-announcement__text"><%= @announcement[:text] %></span>
11
+ <% end %>
12
+
13
+ <% if @announcement[:button] %>
14
+ <a href="<%= @announcement[:button][:link] %>" class="docyard-announcement__button">
15
+ <%= @announcement[:button][:text] %>
16
+ </a>
17
+ <% end %>
18
+ </div>
19
+
20
+ <% if @announcement[:dismissible] %>
21
+ <button class="docyard-announcement__dismiss" aria-label="Dismiss announcement">
22
+ <%= icon("x") %>
23
+ </button>
24
+ <% end %>
25
+ </div>
26
+ <script>document.body.classList.add('has-announcement');</script>
27
+ <% end %>
@@ -0,0 +1,24 @@
1
+ <% if @breadcrumbs&.should_show? %>
2
+ <nav class="breadcrumbs<%= ' breadcrumbs--single' if @breadcrumbs.items.length == 1 %>" aria-label="Breadcrumb">
3
+ <button class="breadcrumb-toggle" aria-label="Toggle sidebar" aria-expanded="true" type="button">
4
+ <%= icon(:sidebar) %>
5
+ </button>
6
+
7
+ <ol class="breadcrumb-list">
8
+ <% @breadcrumbs.items.each_with_index do |item, index| %>
9
+ <li class="breadcrumb-item<%= ' breadcrumb-item--current' if item.current %><%= ' breadcrumb-item--ellipsis' if item.title == '...' %>">
10
+ <% if item.title == '...' %>
11
+ <span class="breadcrumb-ellipsis" aria-hidden="true">...</span>
12
+ <% elsif item.current %>
13
+ <span class="breadcrumb-text" aria-current="page"><%= item.title %></span>
14
+ <% else %>
15
+ <a href="<%= link_path(item.href) %>" class="breadcrumb-link"><%= item.title %></a>
16
+ <% end %>
17
+ </li>
18
+ <% unless index == @breadcrumbs.items.length - 1 %>
19
+ <li class="breadcrumb-separator" aria-hidden="true">/</li>
20
+ <% end %>
21
+ <% end %>
22
+ </ol>
23
+ </nav>
24
+ <% end %>
@@ -0,0 +1,23 @@
1
+ <% if @href %>
2
+ <a href="<%= @href %>" class="docyard-card">
3
+ <% else %>
4
+ <div class="docyard-card">
5
+ <% end %>
6
+ <% if @icon_svg %>
7
+ <div class="docyard-card__icon">
8
+ <%= @icon_svg %>
9
+ </div>
10
+ <% end %>
11
+ <div class="docyard-card__content">
12
+ <h3 class="docyard-card__title"><%= @title %></h3>
13
+ <% unless @content_html.empty? %>
14
+ <div class="docyard-card__body">
15
+ <%= @content_html %>
16
+ </div>
17
+ <% end %>
18
+ </div>
19
+ <% if @href %>
20
+ </a>
21
+ <% else %>
22
+ </div>
23
+ <% end %>
@@ -2,11 +2,12 @@
2
2
  <% if has_title %>
3
3
  <div class="docyard-code-block__header">
4
4
  <% if @icon %>
5
- <span class="docyard-code-block__icon"><% if @icon_source == "file-extension" %><%= Docyard::Icons.render_file_extension(@icon) %><% elsif @icon_source == "phosphor" %><%= Docyard::Icons.render(@icon) %><% end %></span>
5
+ <span class="docyard-code-block__icon"><% if @icon_source == "file-extension" %><%= icon_file_extension(@icon) %><% elsif @icon_source == "phosphor" %><%= icon(@icon) %><% end %></span>
6
6
  <% end %>
7
7
  <span class="docyard-code-block__title" title="<%= @title %>"><%= @title %></span>
8
8
  <button class="docyard-code-block__copy" aria-label="Copy code to clipboard" data-code="<%= @code_text %>">
9
- <%= @copy_icon %>
9
+ <span class="docyard-code-block__copy-icon"><%= @copy_icon %></span>
10
+ <span class="docyard-code-block__copy-text">Copy</span>
10
11
  </button>
11
12
  </div>
12
13
  <% end %>
@@ -47,7 +48,8 @@
47
48
  </div>
48
49
  <% unless has_title %>
49
50
  <button class="docyard-code-block__copy" aria-label="Copy code to clipboard" data-code="<%= @code_text %>">
50
- <%= @copy_icon %>
51
+ <span class="docyard-code-block__copy-icon"><%= @copy_icon %></span>
52
+ <span class="docyard-code-block__copy-text">Copy</span>
51
53
  </button>
52
54
  <% end %>
53
55
  </div>
@@ -0,0 +1,25 @@
1
+ <% has_social = @social&.any? %>
2
+ <% show_footer = has_social || @credits || @copyright %>
3
+
4
+ <% if show_footer %>
5
+ <div class="site-footer">
6
+ <% if has_social %>
7
+ <div class="site-footer__socials">
8
+ <% @social.each do |social| %>
9
+ <a href="<%= social[:url] %>" class="site-footer__link" target="_blank" rel="noopener noreferrer" aria-label="<%= social[:platform].capitalize %>">
10
+ <%= icon(social[:icon]) %>
11
+ </a>
12
+ <% end %>
13
+ </div>
14
+ <% end %>
15
+
16
+ <div class="site-footer__credits">
17
+ <% if @credits %>
18
+ <a href="https://docyard.dev" target="_blank" rel="noopener noreferrer" class="site-footer__attribution">Built with Docyard</a>
19
+ <% end %>
20
+ <% if @copyright %>
21
+ <span class="site-footer__copyright"><%= icon(:copyright) %> <%= @copyright %></span>
22
+ <% end %>
23
+ </div>
24
+ </div>
25
+ <% end %>
@@ -0,0 +1,15 @@
1
+ <section class="features">
2
+ <div class="features-grid">
3
+ <% @features.each do |feature| %>
4
+ <div class="feature-card">
5
+ <% if feature[:icon] %>
6
+ <span class="feature-icon"><%= icon(feature[:icon]) %></span>
7
+ <% end %>
8
+ <h3 class="feature-title"><%= feature[:title] %></h3>
9
+ <% if feature[:description] %>
10
+ <p class="feature-description"><%= feature[:description] %></p>
11
+ <% end %>
12
+ </div>
13
+ <% end %>
14
+ </div>
15
+ </section>
@@ -0,0 +1,42 @@
1
+ <% has_footer_links = @footer_links&.any? %>
2
+ <% has_social = @social&.any? %>
3
+ <% show_footer = has_footer_links || has_social || @credits %>
4
+
5
+ <% if show_footer %>
6
+ <footer class="footer">
7
+ <%
8
+ # Determine layout class
9
+ footer_class = "footer-content"
10
+ if !@credits && !has_social && has_footer_links
11
+ footer_class += " footer-content--no-attribution"
12
+ elsif !has_footer_links && !has_social && @credits
13
+ footer_class += " footer-content--centered"
14
+ elsif !has_footer_links && has_social && !@credits
15
+ footer_class += " footer-content--centered"
16
+ end
17
+ %>
18
+ <div class="<%= footer_class %>">
19
+ <% if @credits %>
20
+ <a href="https://docyard.org" target="_blank" rel="noopener noreferrer" class="footer-attribution">Built with Docyard</a>
21
+ <% end %>
22
+
23
+ <% if has_footer_links %>
24
+ <nav class="footer-links">
25
+ <% @footer_links.each do |link| %>
26
+ <a href="<%= link[:link]&.start_with?('http') ? link[:link] : link_path(link[:link]) %>"<%= link[:link]&.start_with?('http') ? ' target="_blank" rel="noopener noreferrer"' : '' %>><%= link[:text] %></a>
27
+ <% end %>
28
+ </nav>
29
+ <% end %>
30
+
31
+ <% if has_social %>
32
+ <div class="footer-socials">
33
+ <% @social.each do |social| %>
34
+ <a href="<%= social[:url] %>" target="_blank" rel="noopener noreferrer" aria-label="<%= social[:platform].capitalize %>">
35
+ <%= icon(social[:icon]) %>
36
+ </a>
37
+ <% end %>
38
+ </div>
39
+ <% end %>
40
+ </div>
41
+ </footer>
42
+ <% end %>
@@ -0,0 +1,22 @@
1
+ <meta charset="UTF-8">
2
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
3
+ <meta name="description" content="<%= @site_description %>">
4
+ <meta name="view-transition" content="same-origin">
5
+ <title><%= @page_title %> | <%= @site_title %></title>
6
+ <link rel="icon" href="<%= asset_path(@favicon) %>" type="image/svg+xml">
7
+
8
+ <link rel="preload" href="/_docyard/fonts/Inter-Variable.ttf" as="font" type="font/ttf" crossorigin>
9
+
10
+ <script>
11
+ (function() {
12
+ const theme = localStorage.getItem('theme') ||
13
+ (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
14
+ document.documentElement.classList.toggle('dark', theme === 'dark');
15
+
16
+ if (localStorage.getItem('docyard_sidebar_collapsed') === 'true') {
17
+ document.documentElement.classList.add('sidebar-collapsed');
18
+ }
19
+ })();
20
+ </script>
21
+
22
+ <link rel="stylesheet" href="/_docyard/css/main.css">
@@ -0,0 +1,49 @@
1
+ <header class="header">
2
+ <div class="header-content">
3
+ <a href="<%= link_path('/') %>" class="header-logo">
4
+ <% if @has_custom_logo %>
5
+ <div class="site-logo-container">
6
+ <img src="<%= asset_path(@logo) %>" alt="<%= @site_title %>" class="site-logo site-logo-light">
7
+ <% if @logo_dark %>
8
+ <img src="<%= asset_path(@logo_dark) %>" alt="<%= @site_title %>" class="site-logo site-logo-dark">
9
+ <% else %>
10
+ <img src="<%= asset_path(@logo) %>" alt="<%= @site_title %>" class="site-logo site-logo-dark">
11
+ <% end %>
12
+ </div>
13
+ <% else %>
14
+ <span class="header-title"><%= @site_title %></span>
15
+ <% end %>
16
+ </a>
17
+
18
+ <% if @search_enabled %>
19
+ <div class="header-center">
20
+ <%= render_partial('_search_trigger') %>
21
+ </div>
22
+ <% end %>
23
+
24
+ <div class="header-actions">
25
+ <% if @header_ctas&.any? %>
26
+ <div class="header-ctas">
27
+ <% @header_ctas.sort_by { |cta| cta[:variant] == 'secondary' ? 0 : 1 }.each do |cta| %>
28
+ <a href="<%= cta[:external] ? cta[:href] : link_path(cta[:href]) %>"
29
+ class="header-cta header-cta--<%= cta[:variant] || 'primary' %>"
30
+ <%= 'target="_blank" rel="noopener noreferrer"' if cta[:external] %>>
31
+ <%= cta[:text] %>
32
+ <% if cta[:variant] != 'secondary' %>
33
+ <svg class="header-cta-arrow" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
34
+ <path d="M9 5l7 7-7 7"/>
35
+ </svg>
36
+ <% end %>
37
+ </a>
38
+ <% end %>
39
+ </div>
40
+ <% end %>
41
+ <%= render_partial('_theme_toggle') %>
42
+ <% if @has_tabs %>
43
+ <button class="nav-menu-btn" id="navMenuBtn" aria-label="Toggle navigation menu" aria-expanded="false">
44
+ <%= icon(:equals) %>
45
+ </button>
46
+ <% end %>
47
+ </div>
48
+ </div>
49
+ </header>
@@ -1 +1,3 @@
1
- <a href="#<%= @id %>" class="heading-anchor" aria-label="Link to this section" data-heading-id="<%= @id %>" data-pagefind-ignore>#</a>
1
+ <a href="#<%= @id %>" class="heading-anchor" aria-label="Link to this section" data-heading-id="<%= @id %>" data-pagefind-ignore>
2
+ <%= icon(:link_simple) %>
3
+ </a>
@@ -0,0 +1,27 @@
1
+ <section class="hero">
2
+ <div class="hero-content">
3
+ <% if @title %>
4
+ <h1 class="hero-title"><%= @title %></h1>
5
+ <% end %>
6
+ <% if @tagline %>
7
+ <p class="hero-tagline"><%= @tagline %></p>
8
+ <% end %>
9
+ <% if @actions&.any? %>
10
+ <div class="hero-actions">
11
+ <% @actions.each do |action| %>
12
+ <a href="<%= link_path(action[:link]) %>" class="hero-action hero-action--<%= action[:variant] || 'primary' %>">
13
+ <%= action[:text] %>
14
+ <% if action[:variant] == "primary" || action[:variant].nil? %>
15
+ <%= icon(:arrow_right) %>
16
+ <% end %>
17
+ </a>
18
+ <% end %>
19
+ </div>
20
+ <% end %>
21
+ </div>
22
+ <% if @image %>
23
+ <div class="hero-image">
24
+ <img src="<%= link_path(@image[:src]) %>" alt="<%= @image[:alt] || '' %>">
25
+ </div>
26
+ <% end %>
27
+ </section>
@@ -1,13 +1,33 @@
1
1
  <% collapsed = @collapsed || false %>
2
- <button class="nav-group-toggle" aria-expanded="<%= collapsed ? 'false' : 'true' %>" type="button">
3
- <span class="nav-group-title">
4
- <% if @icon %>
5
- <span class="nav-item-icon"><%= icon(@icon) %></span>
6
- <% end %>
7
- <span class="nav-item-text"><%= @title %></span>
8
- </span>
9
- <span class="nav-group-icon"><%= icon(:caret_right) %></span>
10
- </button>
11
- <div class="nav-group-children<%= ' collapsed' if collapsed %>">
12
- <%= @children_html %>
2
+ <div class="nav-group" data-default-collapsed="<%= collapsed %>">
3
+ <% if @has_index && @path %>
4
+ <a href="<%= link_path(@path) %>" class="nav-group-header nav-group-header--link<%= ' active' if @active %>" data-nav-toggle aria-expanded="<%= collapsed ? 'false' : 'true' %>">
5
+ <span class="nav-group-title">
6
+ <% if @icon %>
7
+ <span class="nav-item-icon"><%= icon(@icon) %></span>
8
+ <% end %>
9
+ <span class="nav-item-text"><%= @title %></span>
10
+ <% if @badge %>
11
+ <span class="docyard-badge docyard-badge--<%= @badge_type || 'default' %>"><%= @badge %></span>
12
+ <% end %>
13
+ </span>
14
+ <span class="nav-group-icon"><%= icon(:caret_right) %></span>
15
+ </a>
16
+ <% else %>
17
+ <button class="nav-group-header nav-group-header--button" type="button" data-nav-toggle aria-expanded="<%= collapsed ? 'false' : 'true' %>" aria-label="Toggle <%= @title %>">
18
+ <span class="nav-group-title">
19
+ <% if @icon %>
20
+ <span class="nav-item-icon"><%= icon(@icon) %></span>
21
+ <% end %>
22
+ <span class="nav-item-text"><%= @title %></span>
23
+ <% if @badge %>
24
+ <span class="docyard-badge docyard-badge--<%= @badge_type || 'default' %>"><%= @badge %></span>
25
+ <% end %>
26
+ </span>
27
+ <span class="nav-group-icon"><%= icon(:caret_right) %></span>
28
+ </button>
29
+ <% end %>
30
+ <div class="nav-group-children<%= ' collapsed' if collapsed %>">
31
+ <%= @children_html %>
32
+ </div>
13
33
  </div>
@@ -1,8 +1,11 @@
1
- <a href="<%= link_path(@path) %>"<%= ' class="active"' if @active %><%= " target=\"#{@target}\" rel=\"noopener noreferrer\"" if @target && @target != "_self" %>>
1
+ <a href="<%= link_path(@path) %>"<%= ' class="active"' if @active %> title="<%= @title %>"<%= " target=\"#{@target}\" rel=\"noopener noreferrer\"" if @target && @target != "_self" %>>
2
2
  <% if @icon %>
3
3
  <span class="nav-item-icon"><%= icon(@icon) %></span>
4
4
  <% end %>
5
5
  <span class="nav-item-text"><%= @title %></span>
6
+ <% if @badge %>
7
+ <span class="docyard-badge docyard-badge--<%= @badge_type || 'default' %>"><%= @badge %></span>
8
+ <% end %>
6
9
  <% if @target == "_blank" %>
7
10
  <span class="nav-item-external"><%= icon(:link_external) %></span>
8
11
  <% end %>
@@ -0,0 +1,42 @@
1
+ <% if @has_tabs %>
2
+ <div class="nav-menu-overlay" id="navMenuOverlay" aria-hidden="true"></div>
3
+ <div class="nav-menu-dropdown" id="navMenuDropdown" role="dialog" aria-label="Navigation menu">
4
+ <div class="nav-menu-content">
5
+ <% @tabs.each do |tab| %>
6
+ <a href="<%= tab[:external] ? tab[:href] : link_path(tab[:href]) %>"
7
+ class="nav-menu-item<%= ' is-active' if tab[:active] %>"
8
+ <%= 'target="_blank" rel="noopener noreferrer"' if tab[:external] %>>
9
+ <% if tab[:icon] %>
10
+ <span class="nav-menu-item-icon"><%= icon(tab[:icon].to_sym) %></span>
11
+ <% end %>
12
+ <span class="nav-menu-item-text"><%= tab[:text] %></span>
13
+ <% if tab[:external] %>
14
+ <svg class="nav-menu-item-external" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
15
+ <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path>
16
+ <polyline points="15 3 21 3 21 9"></polyline>
17
+ <line x1="10" y1="14" x2="21" y2="3"></line>
18
+ </svg>
19
+ <% end %>
20
+ </a>
21
+ <% end %>
22
+
23
+ <% if @header_ctas&.any? %>
24
+ <div class="nav-menu-divider"></div>
25
+ <div class="nav-menu-ctas">
26
+ <% @header_ctas.sort_by { |cta| cta[:variant] == 'secondary' ? 0 : 1 }.each do |cta| %>
27
+ <a href="<%= cta[:external] ? cta[:href] : link_path(cta[:href]) %>"
28
+ class="nav-menu-cta nav-menu-cta--<%= cta[:variant] || 'primary' %>"
29
+ <%= 'target="_blank" rel="noopener noreferrer"' if cta[:external] %>>
30
+ <%= cta[:text] %>
31
+ <% if cta[:variant] != 'secondary' %>
32
+ <svg class="nav-menu-cta-arrow" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
33
+ <path d="M9 5l7 7-7 7"/>
34
+ </svg>
35
+ <% end %>
36
+ </a>
37
+ <% end %>
38
+ </div>
39
+ <% end %>
40
+ </div>
41
+ </div>
42
+ <% end %>
@@ -0,0 +1,11 @@
1
+ <div class="nav-nested-section">
2
+ <h6 class="nav-nested-section-title">
3
+ <% if @icon %>
4
+ <span class="nav-item-icon"><%= icon(@icon) %></span>
5
+ <% end %>
6
+ <span class="nav-item-text"><%= @title %></span>
7
+ </h6>
8
+ <div class="nav-nested-section-children">
9
+ <%= @children_html %>
10
+ </div>
11
+ </div>
@@ -1,6 +1,6 @@
1
1
  <div class="nav-section">
2
2
  <% if @section_name %>
3
- <div class="nav-section-title"><%= @section_name %></div>
3
+ <h5 class="nav-section-title"><% if @section_icon %><span class="nav-section-icon"><%= icon(@section_icon) %></span> <% end %><%= @section_name %></h5>
4
4
  <% end %>
5
5
  <%= @section_content %>
6
6
  </div>
@@ -5,7 +5,10 @@
5
5
 
6
6
  <% if @prev %>
7
7
  <a href="<%= link_path(@prev[:path]) %>" class="pager-link prev" title="<%= @prev[:title] %>">
8
- <span class="pager-label"><%= @prev_text %></span>
8
+ <span class="pager-label">
9
+ <%= icon("arrow-left") %>
10
+ <%= @prev_text %>
11
+ </span>
9
12
  <span class="pager-title"><%= @prev[:title] %></span>
10
13
  </a>
11
14
  <% else %>
@@ -14,7 +17,10 @@
14
17
 
15
18
  <% if @next %>
16
19
  <a href="<%= link_path(@next[:path]) %>" class="pager-link next" title="<%= @next[:title] %>">
17
- <span class="pager-label"><%= @next_text %></span>
20
+ <span class="pager-label">
21
+ <%= @next_text %>
22
+ <%= icon("arrow-right") %>
23
+ </span>
18
24
  <span class="pager-title"><%= @next[:title] %></span>
19
25
  </a>
20
26
  <% end %>
@@ -0,0 +1,7 @@
1
+ <% if @search_enabled %>
2
+ <%= render_partial('_search_modal') %>
3
+ <% end %>
4
+
5
+ <script src="/_docyard/js/theme.js"></script>
6
+ <script src="/_docyard/js/components.js"></script>
7
+ <script src="/_docyard/js/reload.js"></script>