docyard 0.9.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +43 -0
  3. data/README.md +8 -253
  4. data/exe/docyard +6 -0
  5. data/lib/docyard/build/asset_bundler.rb +2 -2
  6. data/lib/docyard/build/file_copier.rb +12 -5
  7. data/lib/docyard/build/llms_txt_generator.rb +103 -0
  8. data/lib/docyard/build/sitemap_generator.rb +1 -1
  9. data/lib/docyard/build/static_generator.rb +115 -79
  10. data/lib/docyard/builder.rb +6 -2
  11. data/lib/docyard/cli.rb +14 -4
  12. data/lib/docyard/components/processors/callout_processor.rb +1 -1
  13. data/lib/docyard/components/processors/code_block_extended_fence_postprocessor.rb +24 -0
  14. data/lib/docyard/components/processors/code_block_extended_fence_preprocessor.rb +44 -0
  15. data/lib/docyard/components/processors/code_block_options_preprocessor.rb +11 -1
  16. data/lib/docyard/components/processors/code_block_processor.rb +5 -24
  17. data/lib/docyard/components/processors/code_group_processor.rb +6 -22
  18. data/lib/docyard/components/processors/code_snippet_import_preprocessor.rb +1 -0
  19. data/lib/docyard/components/processors/file_tree_processor.rb +1 -2
  20. data/lib/docyard/components/processors/icon_processor.rb +8 -2
  21. data/lib/docyard/components/processors/include_processor.rb +10 -10
  22. data/lib/docyard/components/processors/video_embed_processor.rb +14 -3
  23. data/lib/docyard/components/support/code_block/feature_extractor.rb +3 -1
  24. data/lib/docyard/components/support/code_block/icon_detector.rb +5 -12
  25. data/lib/docyard/components/support/code_block/line_number_resolver.rb +30 -0
  26. data/lib/docyard/components/support/code_detector.rb +2 -12
  27. data/lib/docyard/components/support/code_group/html_builder.rb +2 -6
  28. data/lib/docyard/components/support/tabs/icon_detector.rb +6 -2
  29. data/lib/docyard/components/support/tabs/parser.rb +6 -23
  30. data/lib/docyard/config/analytics_resolver.rb +24 -0
  31. data/lib/docyard/config/branding_resolver.rb +58 -27
  32. data/lib/docyard/config/key_validator.rb +30 -0
  33. data/lib/docyard/config/logo_detector.rb +8 -8
  34. data/lib/docyard/config/schema.rb +39 -0
  35. data/lib/docyard/config/section.rb +21 -0
  36. data/lib/docyard/config/validation_helpers.rb +83 -0
  37. data/lib/docyard/config/validator.rb +45 -144
  38. data/lib/docyard/config/validators/navigation.rb +43 -0
  39. data/lib/docyard/config/validators/section.rb +114 -0
  40. data/lib/docyard/config.rb +46 -102
  41. data/lib/docyard/constants.rb +59 -0
  42. data/lib/docyard/{utils/errors.rb → errors.rb} +6 -0
  43. data/lib/docyard/initializer.rb +100 -49
  44. data/lib/docyard/navigation/page_navigation_builder.rb +65 -0
  45. data/lib/docyard/navigation/sidebar/auto_builder.rb +107 -0
  46. data/lib/docyard/navigation/sidebar/cache.rb +96 -0
  47. data/lib/docyard/navigation/sidebar/config_builder.rb +179 -0
  48. data/lib/docyard/navigation/sidebar/distributed_builder.rb +145 -0
  49. data/lib/docyard/navigation/sidebar/local_config_loader.rb +69 -3
  50. data/lib/docyard/navigation/sidebar/renderer.rb +12 -1
  51. data/lib/docyard/navigation/sidebar_builder.rb +43 -81
  52. data/lib/docyard/rendering/branding_variables.rb +65 -0
  53. data/lib/docyard/rendering/icon_helpers.rb +14 -1
  54. data/lib/docyard/rendering/icons/devicons.rb +63 -0
  55. data/lib/docyard/rendering/icons.rb +26 -27
  56. data/lib/docyard/rendering/markdown.rb +5 -23
  57. data/lib/docyard/rendering/og_helpers.rb +36 -0
  58. data/lib/docyard/rendering/renderer.rb +87 -59
  59. data/lib/docyard/rendering/template_resolver.rb +14 -0
  60. data/lib/docyard/routing/fallback_resolver.rb +3 -3
  61. data/lib/docyard/search/build_indexer.rb +2 -2
  62. data/lib/docyard/search/dev_indexer.rb +36 -28
  63. data/lib/docyard/search/pagefind_support.rb +1 -1
  64. data/lib/docyard/server/asset_handler.rb +39 -15
  65. data/lib/docyard/server/dev_server.rb +90 -55
  66. data/lib/docyard/server/file_watcher.rb +68 -18
  67. data/lib/docyard/server/pagefind_handler.rb +1 -1
  68. data/lib/docyard/server/preview_server.rb +29 -33
  69. data/lib/docyard/server/rack_application.rb +38 -70
  70. data/lib/docyard/server/router.rb +11 -7
  71. data/lib/docyard/server/sse_server.rb +157 -0
  72. data/lib/docyard/server/static_file_app.rb +42 -0
  73. data/lib/docyard/templates/assets/css/components/banner.css +31 -0
  74. data/lib/docyard/templates/assets/css/components/breadcrumbs.css +2 -1
  75. data/lib/docyard/templates/assets/css/components/callout.css +26 -6
  76. data/lib/docyard/templates/assets/css/components/code-block.css +4 -2
  77. data/lib/docyard/templates/assets/css/components/code-group.css +20 -7
  78. data/lib/docyard/templates/assets/css/components/feedback.css +126 -0
  79. data/lib/docyard/templates/assets/css/components/file-tree.css +5 -4
  80. data/lib/docyard/templates/assets/css/components/icon.css +5 -0
  81. data/lib/docyard/templates/assets/css/components/nav-menu.css +20 -4
  82. data/lib/docyard/templates/assets/css/components/navigation.css +25 -3
  83. data/lib/docyard/templates/assets/css/components/page-actions.css +131 -0
  84. data/lib/docyard/templates/assets/css/components/prev-next.css +14 -7
  85. data/lib/docyard/templates/assets/css/components/search.css +6 -10
  86. data/lib/docyard/templates/assets/css/components/tab-bar.css +7 -4
  87. data/lib/docyard/templates/assets/css/components/table-of-contents.css +57 -11
  88. data/lib/docyard/templates/assets/css/components/tabs.css +12 -4
  89. data/lib/docyard/templates/assets/css/components/theme-toggle.css +3 -1
  90. data/lib/docyard/templates/assets/css/landing.css +82 -13
  91. data/lib/docyard/templates/assets/css/layout.css +17 -0
  92. data/lib/docyard/templates/assets/css/markdown.css +22 -2
  93. data/lib/docyard/templates/assets/css/variables.css +13 -1
  94. data/lib/docyard/templates/assets/js/components/code-group.js +4 -1
  95. data/lib/docyard/templates/assets/js/components/copy-page.js +115 -0
  96. data/lib/docyard/templates/assets/js/components/feedback.js +66 -0
  97. data/lib/docyard/templates/assets/js/components/file-tree.js +5 -5
  98. data/lib/docyard/templates/assets/js/components/navigation.js +3 -3
  99. data/lib/docyard/templates/assets/js/components/search.js +3 -3
  100. data/lib/docyard/templates/assets/js/components/table-of-contents.js +12 -6
  101. data/lib/docyard/templates/assets/js/components/tabs.js +45 -22
  102. data/lib/docyard/templates/assets/js/components/tooltip.js +4 -4
  103. data/lib/docyard/templates/assets/js/hot-reload.js +44 -0
  104. data/lib/docyard/templates/errors/404.html.erb +114 -5
  105. data/lib/docyard/templates/errors/500.html.erb +173 -10
  106. data/lib/docyard/templates/init/_sidebar.yml +36 -0
  107. data/lib/docyard/templates/init/docyard.yml +36 -0
  108. data/lib/docyard/templates/init/pages/components.md +146 -0
  109. data/lib/docyard/templates/init/pages/getting-started.md +94 -0
  110. data/lib/docyard/templates/init/pages/index.md +22 -0
  111. data/lib/docyard/templates/layouts/default.html.erb +10 -0
  112. data/lib/docyard/templates/layouts/splash.html.erb +14 -1
  113. data/lib/docyard/templates/partials/_analytics.html.erb +24 -0
  114. data/lib/docyard/templates/partials/_banner.html.erb +1 -1
  115. data/lib/docyard/templates/partials/_code_block.html.erb +1 -1
  116. data/lib/docyard/templates/partials/_feedback.html.erb +14 -0
  117. data/lib/docyard/templates/partials/_footer.html.erb +1 -1
  118. data/lib/docyard/templates/partials/_head.html.erb +79 -4
  119. data/lib/docyard/templates/partials/_icon_library.html.erb +8 -0
  120. data/lib/docyard/templates/partials/_page_actions.html.erb +21 -0
  121. data/lib/docyard/templates/partials/_scripts.html.erb +6 -3
  122. data/lib/docyard/templates/partials/_tabs.html.erb +4 -1
  123. data/lib/docyard/utils/git_info.rb +157 -0
  124. data/lib/docyard/utils/hash_utils.rb +31 -0
  125. data/lib/docyard/utils/html_helpers.rb +8 -0
  126. data/lib/docyard/utils/logging.rb +44 -3
  127. data/lib/docyard/utils/path_resolver.rb +0 -10
  128. data/lib/docyard/utils/path_utils.rb +73 -0
  129. data/lib/docyard/version.rb +1 -1
  130. data/lib/docyard.rb +2 -2
  131. metadata +77 -47
  132. data/.github/ISSUE_TEMPLATE/bug_report.md +0 -31
  133. data/.github/ISSUE_TEMPLATE/feature_request.md +0 -19
  134. data/.github/pull_request_template.md +0 -14
  135. data/.github/workflows/ci.yml +0 -49
  136. data/.rubocop.yml +0 -42
  137. data/CODE_OF_CONDUCT.md +0 -132
  138. data/CONTRIBUTING.md +0 -55
  139. data/LICENSE.vscode-icons +0 -42
  140. data/Rakefile +0 -8
  141. data/lib/docyard/config/constants.rb +0 -31
  142. data/lib/docyard/navigation/sidebar/children_discoverer.rb +0 -51
  143. data/lib/docyard/navigation/sidebar/config_parser.rb +0 -208
  144. data/lib/docyard/navigation/sidebar/file_resolver.rb +0 -90
  145. data/lib/docyard/navigation/sidebar/file_system_scanner.rb +0 -78
  146. data/lib/docyard/navigation/sidebar/metadata_extractor.rb +0 -71
  147. data/lib/docyard/navigation/sidebar/metadata_reader.rb +0 -51
  148. data/lib/docyard/navigation/sidebar/path_prefixer.rb +0 -34
  149. data/lib/docyard/navigation/sidebar/sorter.rb +0 -21
  150. data/lib/docyard/navigation/sidebar/title_extractor.rb +0 -25
  151. data/lib/docyard/navigation/sidebar/tree_builder.rb +0 -140
  152. data/lib/docyard/rendering/icons/LICENSE.phosphor +0 -21
  153. data/lib/docyard/rendering/icons/file_types.rb +0 -79
  154. data/lib/docyard/rendering/icons/phosphor.rb +0 -93
  155. data/lib/docyard/rendering/language_mapping.rb +0 -52
  156. data/lib/docyard/templates/assets/js/reload.js +0 -98
  157. data/lib/docyard/templates/partials/_icon.html.erb +0 -1
  158. data/lib/docyard/templates/partials/_icon_file_extension.html.erb +0 -1
  159. data/sig/docyard.rbs +0 -4
@@ -16,6 +16,7 @@ class TabsManager {
16
16
  this.handleKeyDown = this.handleKeyDown.bind(this);
17
17
  this.handleResize = this.handleResize.bind(this);
18
18
  this.handleScroll = this.handleScroll.bind(this);
19
+ this.handleTabSync = this.handleTabSync.bind(this);
19
20
 
20
21
  this.init();
21
22
  }
@@ -30,9 +31,12 @@ class TabsManager {
30
31
  this.loadPreference();
31
32
  this.attachEventListeners();
32
33
  this.activateTab(this.activeIndex, false);
33
- this.updateIndicator();
34
+ this.updateIndicator(false);
34
35
 
35
36
  requestAnimationFrame(() => {
37
+ if (this.indicator) {
38
+ this.indicator.classList.add('is-ready');
39
+ }
36
40
  requestAnimationFrame(() => {
37
41
  this.updateScrollIndicators();
38
42
  });
@@ -63,6 +67,8 @@ class TabsManager {
63
67
  this.tabList.addEventListener('scroll', this.handleScroll);
64
68
 
65
69
  window.addEventListener('resize', this.handleResize);
70
+
71
+ window.addEventListener('docyard-tab-change', this.handleTabSync);
66
72
  }
67
73
 
68
74
 
@@ -70,7 +76,36 @@ class TabsManager {
70
76
  if (index === this.activeIndex) return;
71
77
 
72
78
  this.activateTab(index, true);
73
- this.savePreference(index);
79
+ this.broadcastTabChange(index);
80
+ }
81
+
82
+ handleTabSync(event) {
83
+ if (event.detail.sourceId === this.groupId) return;
84
+
85
+ const tabName = event.detail.tabName;
86
+ const index = this.tabs.findIndex(tab =>
87
+ tab.getAttribute('data-tab-name') === tabName
88
+ );
89
+
90
+ if (index !== -1 && index !== this.activeIndex) {
91
+ this.activateTab(index, true);
92
+ }
93
+ }
94
+
95
+ broadcastTabChange(index) {
96
+ if (index < 0 || index >= this.tabs.length) return;
97
+
98
+ const tabName = this.tabs[index].getAttribute('data-tab-name');
99
+
100
+ try {
101
+ localStorage.setItem('docyard-preferred-pm', tabName);
102
+ } catch (error) {
103
+ // Silently fail if localStorage is unavailable
104
+ }
105
+
106
+ window.dispatchEvent(new CustomEvent('docyard-tab-change', {
107
+ detail: { tabName, sourceId: this.groupId }
108
+ }));
74
109
  }
75
110
 
76
111
 
@@ -92,6 +127,7 @@ class TabsManager {
92
127
  if (key === 'Home') {
93
128
  event.preventDefault();
94
129
  this.activateTab(0, true);
130
+ this.broadcastTabChange(0);
95
131
  this.tabs[0].focus();
96
132
  }
97
133
 
@@ -99,6 +135,7 @@ class TabsManager {
99
135
  event.preventDefault();
100
136
  const lastIndex = this.tabs.length - 1;
101
137
  this.activateTab(lastIndex, true);
138
+ this.broadcastTabChange(lastIndex);
102
139
  this.tabs[lastIndex].focus();
103
140
  }
104
141
  }
@@ -153,22 +190,20 @@ class TabsManager {
153
190
  });
154
191
 
155
192
  this.updateIndicator(animate);
156
-
157
- if (previousIndex !== index) {
158
- this.savePreference(index);
159
- }
160
193
  }
161
194
 
162
195
 
163
196
  activateNextTab() {
164
197
  const nextIndex = (this.activeIndex + 1) % this.tabs.length;
165
198
  this.activateTab(nextIndex, true);
199
+ this.broadcastTabChange(nextIndex);
166
200
  }
167
201
 
168
-
202
+
169
203
  activatePreviousTab() {
170
204
  const prevIndex = (this.activeIndex - 1 + this.tabs.length) % this.tabs.length;
171
205
  this.activateTab(prevIndex, true);
206
+ this.broadcastTabChange(prevIndex);
172
207
  }
173
208
 
174
209
 
@@ -227,7 +262,7 @@ class TabsManager {
227
262
  if (!preferredTab) return;
228
263
 
229
264
  const index = this.tabs.findIndex(tab =>
230
- tab.textContent.trim().toLowerCase() === preferredTab.toLowerCase()
265
+ tab.getAttribute('data-tab-name') === preferredTab
231
266
  );
232
267
 
233
268
  if (index !== -1) {
@@ -238,22 +273,9 @@ class TabsManager {
238
273
  }
239
274
  }
240
275
 
241
-
242
- savePreference(index) {
243
- if (index < 0 || index >= this.tabs.length) return;
244
-
245
- try {
246
- const tabName = this.tabs[index].textContent.trim().toLowerCase();
247
- localStorage.setItem('docyard-preferred-pm', tabName);
248
- } catch (error) {
249
- console.warn('Could not save tab preference:', error);
250
- }
251
- }
252
-
253
-
254
276
  activateTabByName(name) {
255
277
  const index = this.tabs.findIndex(tab =>
256
- tab.textContent.trim().toLowerCase() === name.toLowerCase()
278
+ tab.getAttribute('data-tab-name') === name.toLowerCase()
257
279
  );
258
280
 
259
281
  if (index !== -1) {
@@ -270,6 +292,7 @@ class TabsManager {
270
292
  this.tabList.removeEventListener('keydown', this.handleKeyDown);
271
293
  this.tabList.removeEventListener('scroll', this.handleScroll);
272
294
  window.removeEventListener('resize', this.handleResize);
295
+ window.removeEventListener('docyard-tab-change', this.handleTabSync);
273
296
 
274
297
  if (this.resizeTimeout) {
275
298
  cancelAnimationFrame(this.resizeTimeout);
@@ -11,20 +11,20 @@ function initializeTooltips() {
11
11
  popover.addEventListener('mouseenter', () => {
12
12
  isHoveringPopover = true;
13
13
  clearTimeout(hideTimeout);
14
- });
14
+ }, { passive: true });
15
15
 
16
16
  popover.addEventListener('mouseleave', () => {
17
17
  isHoveringPopover = false;
18
18
  hideTimeout = setTimeout(() => {
19
19
  hideTooltipPopover(popover);
20
20
  }, 100);
21
- });
21
+ }, { passive: true });
22
22
 
23
23
  tooltips.forEach(tooltip => {
24
24
  tooltip.addEventListener('mouseenter', () => {
25
25
  clearTimeout(hideTimeout);
26
26
  showTooltipPopover(popover, tooltip);
27
- });
27
+ }, { passive: true });
28
28
 
29
29
  tooltip.addEventListener('mouseleave', () => {
30
30
  hideTimeout = setTimeout(() => {
@@ -32,7 +32,7 @@ function initializeTooltips() {
32
32
  hideTooltipPopover(popover);
33
33
  }
34
34
  }, 100);
35
- });
35
+ }, { passive: true });
36
36
  });
37
37
  }
38
38
 
@@ -0,0 +1,44 @@
1
+ (function() {
2
+ var ssePort = window.__DOCYARD_SSE_PORT__;
3
+ if (!ssePort) return;
4
+
5
+ var url = 'http://127.0.0.1:' + ssePort + '/';
6
+ var eventSource = new EventSource(url);
7
+
8
+ eventSource.addEventListener('reload', function(event) {
9
+ var data = JSON.parse(event.data);
10
+ if (data.type === 'content') {
11
+ console.log('[Docyard] Content updated');
12
+ reloadContent();
13
+ } else {
14
+ console.log('[Docyard] Full reload');
15
+ location.reload();
16
+ }
17
+ });
18
+
19
+ eventSource.onerror = function() {
20
+ eventSource.close();
21
+ };
22
+
23
+ function reloadContent() {
24
+ fetch(location.href)
25
+ .then(function(response) { return response.text(); })
26
+ .then(function(html) {
27
+ var parser = new DOMParser();
28
+ var newDoc = parser.parseFromString(html, 'text/html');
29
+ var newContent = newDoc.querySelector('.content');
30
+ var currentContent = document.querySelector('.content');
31
+
32
+ if (newContent && currentContent) {
33
+ currentContent.innerHTML = newContent.innerHTML;
34
+ if (window.Prism) window.Prism.highlightAll();
35
+ if (window.docyardTOC) window.docyardTOC.init();
36
+ } else {
37
+ location.reload();
38
+ }
39
+ })
40
+ .catch(function() {
41
+ location.reload();
42
+ });
43
+ }
44
+ })();
@@ -4,13 +4,122 @@
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>404 - Page Not Found</title>
7
- <link rel="stylesheet" href="/_docyard/css/main.css">
7
+ <style>
8
+ @font-face {
9
+ font-family: 'Inter';
10
+ src: url('/_docyard/fonts/Inter-Variable.ttf') format('truetype');
11
+ font-weight: 100 900;
12
+ font-style: normal;
13
+ }
14
+
15
+ :root {
16
+ --background: #ffffff;
17
+ --foreground: #0f0f10;
18
+ --muted-foreground: #71717a;
19
+ --border: #e4e4e7;
20
+ --primary: oklch(0.61 0.11 222);
21
+ --primary-foreground: oklch(0.98 0.02 201);
22
+ --radius: 0.5rem;
23
+ }
24
+
25
+ .dark {
26
+ --background: #09090b;
27
+ --foreground: #fafafa;
28
+ --muted-foreground: #a1a1aa;
29
+ --border: #27272a;
30
+ --primary: oklch(0.71 0.13 215);
31
+ --primary-foreground: oklch(0.30 0.05 230);
32
+ }
33
+
34
+ * {
35
+ margin: 0;
36
+ padding: 0;
37
+ box-sizing: border-box;
38
+ }
39
+
40
+ body {
41
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
42
+ background: var(--background);
43
+ color: var(--foreground);
44
+ min-height: 100vh;
45
+ display: flex;
46
+ align-items: center;
47
+ justify-content: center;
48
+ padding: 2rem;
49
+ }
50
+
51
+ .error-page {
52
+ text-align: center;
53
+ max-width: 450px;
54
+ }
55
+
56
+ .error-code {
57
+ font-size: 8rem;
58
+ font-weight: 700;
59
+ color: transparent;
60
+ -webkit-text-stroke: 2px var(--border);
61
+ line-height: 1;
62
+ }
63
+
64
+ .error-title {
65
+ font-size: 1.25rem;
66
+ font-weight: 600;
67
+ margin: 1rem 0 0.5rem;
68
+ }
69
+
70
+ .error-message {
71
+ color: var(--muted-foreground);
72
+ font-size: 0.9375rem;
73
+ margin-bottom: 1.5rem;
74
+ }
75
+
76
+ .btn {
77
+ display: inline-flex;
78
+ align-items: center;
79
+ gap: 0.5rem;
80
+ padding: 0.5rem 1rem;
81
+ font-size: 0.875rem;
82
+ font-weight: 500;
83
+ text-decoration: none;
84
+ border-radius: var(--radius);
85
+ background: var(--primary);
86
+ color: var(--primary-foreground);
87
+ transition: opacity 0.15s;
88
+ font-family: inherit;
89
+ }
90
+
91
+ .btn:hover {
92
+ opacity: 0.9;
93
+ }
94
+
95
+ .btn svg {
96
+ width: 16px;
97
+ height: 16px;
98
+ }
99
+
100
+ @media (max-width: 480px) {
101
+ .error-code {
102
+ font-size: 5rem;
103
+ }
104
+ }
105
+ </style>
106
+ <script>
107
+ (function() {
108
+ const theme = localStorage.getItem('theme') ||
109
+ (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
110
+ document.documentElement.classList.toggle('dark', theme === 'dark');
111
+ })();
112
+ </script>
8
113
  </head>
9
114
  <body>
10
- <main>
11
- <h1>404 - Page Not Found</h1>
12
- <p>The page you're looking for doesn't exist.</p>
13
- <p><a href="/">Go back home</a></p>
115
+ <main class="error-page">
116
+ <p class="error-code">404</p>
117
+ <h1 class="error-title">Page not found</h1>
118
+ <p class="error-message">This page doesn't exist or has been moved.</p>
119
+ <a href="/" class="btn">
120
+ <%= icon(:house_line) %>
121
+ Back to home
122
+ </a>
14
123
  </main>
15
124
  </body>
16
125
  </html>
@@ -4,21 +4,184 @@
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>500 - Server Error</title>
7
- <link rel="stylesheet" href="/_docyard/css/main.css">
7
+ <style>
8
+ @font-face {
9
+ font-family: 'Inter';
10
+ src: url('/_docyard/fonts/Inter-Variable.ttf') format('truetype');
11
+ font-weight: 100 900;
12
+ font-style: normal;
13
+ }
14
+
15
+ :root {
16
+ --background: #ffffff;
17
+ --foreground: #0f0f10;
18
+ --muted: #f5f5f6;
19
+ --muted-foreground: #71717a;
20
+ --border: #e4e4e7;
21
+ --primary: oklch(0.61 0.11 222);
22
+ --primary-foreground: oklch(0.98 0.02 201);
23
+ --destructive: #dc2626;
24
+ --radius: 0.5rem;
25
+ }
26
+
27
+ .dark {
28
+ --background: #09090b;
29
+ --foreground: #fafafa;
30
+ --muted: #18181b;
31
+ --muted-foreground: #a1a1aa;
32
+ --border: #27272a;
33
+ --primary: oklch(0.71 0.13 215);
34
+ --primary-foreground: oklch(0.30 0.05 230);
35
+ --destructive: #f87171;
36
+ }
37
+
38
+ * {
39
+ margin: 0;
40
+ padding: 0;
41
+ box-sizing: border-box;
42
+ }
43
+
44
+ body {
45
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
46
+ background: var(--background);
47
+ color: var(--foreground);
48
+ min-height: 100vh;
49
+ display: flex;
50
+ align-items: center;
51
+ justify-content: center;
52
+ padding: 2rem;
53
+ }
54
+
55
+ .error-page {
56
+ text-align: center;
57
+ max-width: 500px;
58
+ }
59
+
60
+ .error-code {
61
+ font-size: 8rem;
62
+ font-weight: 700;
63
+ color: transparent;
64
+ -webkit-text-stroke: 2px var(--border);
65
+ line-height: 1;
66
+ }
67
+
68
+ .error-title {
69
+ font-size: 1.25rem;
70
+ font-weight: 600;
71
+ margin: 1rem 0 0.5rem;
72
+ }
73
+
74
+ .error-message {
75
+ color: var(--muted-foreground);
76
+ font-size: 0.9375rem;
77
+ margin-bottom: 1.5rem;
78
+ }
79
+
80
+ .btn {
81
+ display: inline-flex;
82
+ align-items: center;
83
+ gap: 0.5rem;
84
+ padding: 0.5rem 1rem;
85
+ font-size: 0.875rem;
86
+ font-weight: 500;
87
+ text-decoration: none;
88
+ border-radius: var(--radius);
89
+ background: var(--primary);
90
+ color: var(--primary-foreground);
91
+ transition: opacity 0.15s;
92
+ font-family: inherit;
93
+ }
94
+
95
+ .btn:hover {
96
+ opacity: 0.9;
97
+ }
98
+
99
+ .btn svg {
100
+ width: 16px;
101
+ height: 16px;
102
+ }
103
+
104
+ .error-details {
105
+ margin-top: 2rem;
106
+ text-align: left;
107
+ background: var(--muted);
108
+ border: 1px solid var(--border);
109
+ border-radius: var(--radius);
110
+ overflow: hidden;
111
+ }
112
+
113
+ .error-details summary {
114
+ cursor: pointer;
115
+ padding: 0.75rem 1rem;
116
+ font-size: 0.8125rem;
117
+ font-weight: 500;
118
+ color: var(--muted-foreground);
119
+ display: flex;
120
+ align-items: center;
121
+ gap: 0.5rem;
122
+ }
123
+
124
+ .error-details summary svg {
125
+ width: 14px;
126
+ height: 14px;
127
+ }
128
+
129
+ .error-details[open] summary {
130
+ border-bottom: 1px solid var(--border);
131
+ }
132
+
133
+ .error-details pre {
134
+ margin: 0;
135
+ padding: 1rem;
136
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
137
+ font-size: 0.75rem;
138
+ line-height: 1.5;
139
+ color: var(--destructive);
140
+ white-space: pre-wrap;
141
+ word-break: break-word;
142
+ overflow-x: auto;
143
+ }
144
+
145
+ .error-details .backtrace {
146
+ border-top: 1px solid var(--border);
147
+ color: var(--muted-foreground);
148
+ }
149
+
150
+ @media (max-width: 480px) {
151
+ .error-code {
152
+ font-size: 5rem;
153
+ }
154
+ }
155
+ </style>
156
+ <script>
157
+ (function() {
158
+ const theme = localStorage.getItem('theme') ||
159
+ (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
160
+ document.documentElement.classList.toggle('dark', theme === 'dark');
161
+ })();
162
+ </script>
8
163
  </head>
9
164
  <body>
10
- <main>
11
- <h1>500 - Internal Server Error</h1>
12
- <p>Something went wrong.</p>
165
+ <main class="error-page">
166
+ <p class="error-code">500</p>
167
+ <h1 class="error-title">Something went wrong</h1>
168
+ <p class="error-message">We encountered an unexpected error. Please try again.</p>
169
+ <a href="/" class="btn">
170
+ <%= icon(:house_line) %>
171
+ Back to home
172
+ </a>
13
173
 
14
174
  <% if @error_message %>
15
- <h3>Error Details:</h3>
175
+ <details class="error-details">
176
+ <summary>
177
+ <%= icon(:warning_circle) %>
178
+ Error details
179
+ </summary>
16
180
  <pre><%= @error_message %></pre>
17
- <% end %>
18
-
19
- <% if @backtrace %>
20
- <h3>Backtrace:</h3>
21
- <pre><%= @backtrace %></pre>
181
+ <% if @backtrace %>
182
+ <pre class="backtrace"><%= @backtrace %></pre>
183
+ <% end %>
184
+ </details>
22
185
  <% end %>
23
186
  </main>
24
187
  </body>
@@ -0,0 +1,36 @@
1
+ # =============================================================================
2
+ # Sidebar Navigation
3
+ # =============================================================================
4
+ # This file controls the sidebar navigation for your documentation.
5
+ #
6
+ # Basic syntax:
7
+ # - page-name # Links to docs/page-name.md
8
+ # - page-name: { text: "Custom Title", icon: rocket-launch }
9
+ #
10
+ # Sections with nested pages:
11
+ # - section-name:
12
+ # text: "Section Title"
13
+ # icon: folder
14
+ # items:
15
+ # - page-one
16
+ # - page-two
17
+ #
18
+ # External links:
19
+ # - link: "https://github.com/your-org"
20
+ # text: "GitHub"
21
+ # icon: github
22
+ #
23
+ # Available icons: https://phosphoricons.com (use kebab-case names)
24
+ # =============================================================================
25
+
26
+ - index:
27
+ text: Welcome
28
+ icon: house
29
+
30
+ - getting-started:
31
+ text: Getting Started
32
+ icon: rocket-launch
33
+
34
+ - components:
35
+ text: Components
36
+ icon: package
@@ -0,0 +1,36 @@
1
+ # Docyard Configuration
2
+ # Full documentation: https://docyard.dev/configuration
3
+
4
+ title: "{{PROJECT_NAME}}"
5
+ description: "Documentation for {{PROJECT_NAME}}"
6
+
7
+ # Your production URL (for SEO and sitemaps)
8
+ # url: "https://docs.example.com"
9
+
10
+ # Branding customization
11
+ # branding:
12
+ # color: "#3b82f6" # Primary color (or use light/dark below)
13
+ # # color:
14
+ # # light: "#3b82f6"
15
+ # # dark: "#60a5fa"
16
+
17
+ # Social links (shown in footer)
18
+ # socials:
19
+ # github: "https://github.com/your-org/your-repo"
20
+ # twitter: "https://twitter.com/your-handle"
21
+
22
+ # Repository settings (enables "Edit this page" links)
23
+ # repo:
24
+ # url: "https://github.com/your-org/your-repo"
25
+ # branch: "main"
26
+ # edit_link: true
27
+
28
+ # Search (enabled by default)
29
+ search:
30
+ enabled: true
31
+ placeholder: "Search..."
32
+
33
+ # Build output
34
+ build:
35
+ output: "dist"
36
+ base: "/"