docyard 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -1
- data/README.md +55 -33
- data/lib/docyard/build/asset_bundler.rb +139 -0
- data/lib/docyard/build/file_copier.rb +105 -0
- data/lib/docyard/build/sitemap_generator.rb +57 -0
- data/lib/docyard/build/static_generator.rb +141 -0
- data/lib/docyard/builder.rb +104 -0
- data/lib/docyard/cli.rb +19 -0
- data/lib/docyard/components/table_wrapper_processor.rb +18 -0
- data/lib/docyard/config.rb +4 -2
- data/lib/docyard/icons/phosphor.rb +1 -0
- data/lib/docyard/initializer.rb +80 -14
- data/lib/docyard/markdown.rb +13 -0
- data/lib/docyard/preview_server.rb +72 -0
- data/lib/docyard/rack_application.rb +1 -1
- data/lib/docyard/renderer.rb +17 -3
- data/lib/docyard/sidebar/config_parser.rb +180 -0
- data/lib/docyard/sidebar/item.rb +58 -0
- data/lib/docyard/sidebar/renderer.rb +33 -6
- data/lib/docyard/sidebar_builder.rb +45 -1
- data/lib/docyard/templates/assets/css/components/callout.css +1 -1
- data/lib/docyard/templates/assets/css/components/code-block.css +2 -2
- data/lib/docyard/templates/assets/css/components/navigation.css +65 -7
- data/lib/docyard/templates/assets/css/components/tabs.css +3 -2
- data/lib/docyard/templates/assets/css/components/theme-toggle.css +8 -0
- data/lib/docyard/templates/assets/css/markdown.css +20 -11
- data/lib/docyard/templates/assets/js/components/navigation.js +221 -0
- data/lib/docyard/templates/assets/js/theme.js +2 -185
- data/lib/docyard/templates/config/docyard.yml.erb +32 -10
- data/lib/docyard/templates/layouts/default.html.erb +1 -1
- data/lib/docyard/templates/markdown/getting-started/installation.md.erb +46 -12
- data/lib/docyard/templates/markdown/guides/configuration.md.erb +202 -0
- data/lib/docyard/templates/markdown/guides/markdown-features.md.erb +247 -0
- data/lib/docyard/templates/markdown/index.md.erb +55 -59
- data/lib/docyard/templates/partials/_nav_group.html.erb +10 -4
- data/lib/docyard/templates/partials/_nav_leaf.html.erb +9 -1
- data/lib/docyard/version.rb +1 -1
- data/lib/docyard.rb +8 -0
- metadata +55 -10
- data/lib/docyard/templates/markdown/components/callouts.md.erb +0 -204
- data/lib/docyard/templates/markdown/components/icons.md.erb +0 -125
- data/lib/docyard/templates/markdown/components/tabs.md.erb +0 -686
- data/lib/docyard/templates/markdown/configuration.md.erb +0 -202
- data/lib/docyard/templates/markdown/core-concepts/file-structure.md.erb +0 -61
- data/lib/docyard/templates/markdown/core-concepts/markdown.md.erb +0 -90
- data/lib/docyard/templates/markdown/getting-started/introduction.md.erb +0 -30
- data/lib/docyard/templates/markdown/getting-started/quick-start.md.erb +0 -56
- data/lib/docyard/templates/partials/_icons.html.erb +0 -11
|
@@ -7,10 +7,11 @@ module Docyard
|
|
|
7
7
|
class Renderer
|
|
8
8
|
PARTIALS_PATH = File.join(__dir__, "../templates/partials")
|
|
9
9
|
|
|
10
|
-
attr_reader :site_title
|
|
10
|
+
attr_reader :site_title, :base_url
|
|
11
11
|
|
|
12
|
-
def initialize(site_title: "Documentation")
|
|
12
|
+
def initialize(site_title: "Documentation", base_url: "/")
|
|
13
13
|
@site_title = site_title
|
|
14
|
+
@base_url = normalize_base_url(base_url)
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
def render(tree)
|
|
@@ -34,8 +35,21 @@ module Docyard
|
|
|
34
35
|
ERB.new(template).result(erb_binding)
|
|
35
36
|
end
|
|
36
37
|
|
|
37
|
-
def icon(name)
|
|
38
|
-
|
|
38
|
+
def icon(name, weight = "regular")
|
|
39
|
+
Icons.render(name.to_s.tr("_", "-"), weight) || ""
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def link_path(path)
|
|
43
|
+
return path if path.nil? || path.start_with?("http://", "https://")
|
|
44
|
+
|
|
45
|
+
"#{base_url.chomp('/')}#{path}"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def normalize_base_url(url)
|
|
49
|
+
return "/" if url.nil? || url.empty?
|
|
50
|
+
|
|
51
|
+
url = "/#{url}" unless url.start_with?("/")
|
|
52
|
+
url.end_with?("/") ? url : "#{url}/"
|
|
39
53
|
end
|
|
40
54
|
|
|
41
55
|
def render_tree_with_sections(items)
|
|
@@ -98,12 +112,25 @@ module Docyard
|
|
|
98
112
|
end
|
|
99
113
|
|
|
100
114
|
def render_leaf_item(item)
|
|
101
|
-
render_partial(
|
|
115
|
+
render_partial(
|
|
116
|
+
:nav_leaf,
|
|
117
|
+
path: item[:path],
|
|
118
|
+
title: item[:title],
|
|
119
|
+
active: item[:active],
|
|
120
|
+
icon: item[:icon],
|
|
121
|
+
target: item[:target]
|
|
122
|
+
)
|
|
102
123
|
end
|
|
103
124
|
|
|
104
125
|
def render_group_item(item)
|
|
105
126
|
children_html = render_tree(item[:children])
|
|
106
|
-
render_partial(
|
|
127
|
+
render_partial(
|
|
128
|
+
:nav_group,
|
|
129
|
+
title: item[:title],
|
|
130
|
+
children_html: children_html,
|
|
131
|
+
icon: item[:icon],
|
|
132
|
+
collapsed: item[:collapsed]
|
|
133
|
+
)
|
|
107
134
|
end
|
|
108
135
|
end
|
|
109
136
|
end
|
|
@@ -4,6 +4,7 @@ require_relative "sidebar/file_system_scanner"
|
|
|
4
4
|
require_relative "sidebar/title_extractor"
|
|
5
5
|
require_relative "sidebar/tree_builder"
|
|
6
6
|
require_relative "sidebar/renderer"
|
|
7
|
+
require_relative "sidebar/config_parser"
|
|
7
8
|
|
|
8
9
|
module Docyard
|
|
9
10
|
class SidebarBuilder
|
|
@@ -26,10 +27,44 @@ module Docyard
|
|
|
26
27
|
private
|
|
27
28
|
|
|
28
29
|
def build_tree
|
|
30
|
+
if config_sidebar_items?
|
|
31
|
+
build_tree_from_config
|
|
32
|
+
else
|
|
33
|
+
build_tree_from_filesystem
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def build_tree_from_config
|
|
38
|
+
config_parser.parse.map(&:to_h)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def build_tree_from_filesystem
|
|
29
42
|
file_items = scanner.scan
|
|
30
43
|
tree_builder.build(file_items)
|
|
31
44
|
end
|
|
32
45
|
|
|
46
|
+
def config_sidebar_items?
|
|
47
|
+
config_sidebar_items&.any?
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def config_sidebar_items
|
|
51
|
+
return [] unless config
|
|
52
|
+
|
|
53
|
+
if config.is_a?(Hash)
|
|
54
|
+
config.dig("sidebar", "items") || config.dig(:sidebar, :items) || []
|
|
55
|
+
else
|
|
56
|
+
config.sidebar&.items || []
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def config_parser
|
|
61
|
+
@config_parser ||= Sidebar::ConfigParser.new(
|
|
62
|
+
config_sidebar_items,
|
|
63
|
+
docs_path: docs_path,
|
|
64
|
+
current_path: current_path
|
|
65
|
+
)
|
|
66
|
+
end
|
|
67
|
+
|
|
33
68
|
def scanner
|
|
34
69
|
@scanner ||= Sidebar::FileSystemScanner.new(docs_path)
|
|
35
70
|
end
|
|
@@ -43,10 +78,19 @@ module Docyard
|
|
|
43
78
|
|
|
44
79
|
def renderer
|
|
45
80
|
@renderer ||= Sidebar::Renderer.new(
|
|
46
|
-
site_title: extract_site_title
|
|
81
|
+
site_title: extract_site_title,
|
|
82
|
+
base_url: extract_base_url
|
|
47
83
|
)
|
|
48
84
|
end
|
|
49
85
|
|
|
86
|
+
def extract_base_url
|
|
87
|
+
if config.is_a?(Hash)
|
|
88
|
+
config.dig(:build, :base_url) || "/"
|
|
89
|
+
else
|
|
90
|
+
config&.build&.base_url || "/"
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
50
94
|
def extract_site_title
|
|
51
95
|
if config.is_a?(Hash)
|
|
52
96
|
config[:site_title] || "Documentation"
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
background-color: var(--color-bg);
|
|
48
48
|
color: var(--color-text-secondary);
|
|
49
49
|
cursor: pointer;
|
|
50
|
-
transition:
|
|
50
|
+
transition: background-color var(--transition-base), border-color var(--transition-base), color var(--transition-base), opacity var(--transition-base), visibility var(--transition-base);
|
|
51
51
|
opacity: 0;
|
|
52
52
|
visibility: hidden;
|
|
53
53
|
}
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
.docyard-code-block__copy svg {
|
|
79
79
|
width: 16px;
|
|
80
80
|
height: 16px;
|
|
81
|
-
transition:
|
|
81
|
+
transition: transform 0.2s ease, opacity 0.2s ease;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
/* Success state */
|
|
@@ -53,13 +53,15 @@
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
.sidebar nav a {
|
|
56
|
-
display:
|
|
56
|
+
display: flex;
|
|
57
|
+
align-items: center;
|
|
58
|
+
gap: var(--space-2);
|
|
57
59
|
padding: 0.5rem var(--space-3);
|
|
58
60
|
font-size: 0.875rem;
|
|
59
61
|
color: var(--color-text-secondary);
|
|
60
62
|
text-decoration: none;
|
|
61
63
|
border-radius: var(--radius-md);
|
|
62
|
-
transition:
|
|
64
|
+
transition: color var(--transition-fast);
|
|
63
65
|
line-height: 1.4;
|
|
64
66
|
font-weight: var(--font-weight-medium);
|
|
65
67
|
}
|
|
@@ -148,7 +150,7 @@
|
|
|
148
150
|
color: var(--color-text-secondary);
|
|
149
151
|
text-decoration: none;
|
|
150
152
|
border-radius: var(--radius-md);
|
|
151
|
-
transition:
|
|
153
|
+
transition: color var(--transition-fast);
|
|
152
154
|
line-height: 1.4;
|
|
153
155
|
font-weight: var(--font-weight-medium);
|
|
154
156
|
background: none;
|
|
@@ -157,6 +159,13 @@
|
|
|
157
159
|
cursor: pointer;
|
|
158
160
|
}
|
|
159
161
|
|
|
162
|
+
.nav-group-title {
|
|
163
|
+
display: flex;
|
|
164
|
+
align-items: center;
|
|
165
|
+
gap: var(--space-2);
|
|
166
|
+
flex: 1;
|
|
167
|
+
}
|
|
168
|
+
|
|
160
169
|
.nav-group-toggle:hover {
|
|
161
170
|
color: var(--color-text);
|
|
162
171
|
}
|
|
@@ -167,14 +176,18 @@
|
|
|
167
176
|
}
|
|
168
177
|
|
|
169
178
|
.nav-group-icon {
|
|
179
|
+
display: inline-flex;
|
|
180
|
+
color: var(--color-text-tertiary);
|
|
181
|
+
flex-shrink: 0;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.nav-group-icon .docyard-icon {
|
|
170
185
|
width: 1rem;
|
|
171
186
|
height: 1rem;
|
|
172
|
-
color: var(--color-text-tertiary);
|
|
173
187
|
transition: transform var(--transition-fast);
|
|
174
|
-
flex-shrink: 0;
|
|
175
188
|
}
|
|
176
189
|
|
|
177
|
-
.nav-group-toggle[aria-expanded="true"] .nav-group-icon {
|
|
190
|
+
.nav-group-toggle[aria-expanded="true"] .nav-group-icon .docyard-icon {
|
|
178
191
|
transform: rotate(90deg);
|
|
179
192
|
}
|
|
180
193
|
|
|
@@ -225,7 +238,7 @@
|
|
|
225
238
|
text-decoration: none;
|
|
226
239
|
padding: var(--space-2);
|
|
227
240
|
border-radius: var(--radius-md);
|
|
228
|
-
transition:
|
|
241
|
+
transition: background-color var(--transition-fast);
|
|
229
242
|
}
|
|
230
243
|
|
|
231
244
|
.sidebar-footer-link:hover {
|
|
@@ -256,3 +269,48 @@
|
|
|
256
269
|
transition: opacity var(--transition-fast);
|
|
257
270
|
flex-shrink: 0;
|
|
258
271
|
}
|
|
272
|
+
|
|
273
|
+
/* Icon styling */
|
|
274
|
+
.nav-item-icon {
|
|
275
|
+
display: inline-flex;
|
|
276
|
+
align-items: center;
|
|
277
|
+
flex-shrink: 0;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
.nav-item-icon .docyard-icon {
|
|
281
|
+
width: 1rem;
|
|
282
|
+
height: 1rem;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
.nav-item-text {
|
|
286
|
+
flex: 1;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.nav-item-external {
|
|
290
|
+
display: inline-flex;
|
|
291
|
+
align-items: center;
|
|
292
|
+
opacity: 0.5;
|
|
293
|
+
flex-shrink: 0;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
.nav-item-external .docyard-icon {
|
|
297
|
+
width: 0.75rem;
|
|
298
|
+
height: 0.75rem;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/* Reduced motion support */
|
|
302
|
+
@media (prefers-reduced-motion: reduce) {
|
|
303
|
+
.sidebar nav a,
|
|
304
|
+
.nav-group-toggle,
|
|
305
|
+
.nav-group-icon .docyard-icon,
|
|
306
|
+
.nav-group-children,
|
|
307
|
+
.mobile-menu-toggle,
|
|
308
|
+
.sidebar-footer-link,
|
|
309
|
+
.external-icon {
|
|
310
|
+
transition: none;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
.nav-group-toggle[aria-expanded="true"] .nav-group-icon .docyard-icon {
|
|
314
|
+
transform: none;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
font-family: var(--font-sans);
|
|
63
63
|
color: var(--color-text-secondary);
|
|
64
64
|
cursor: pointer;
|
|
65
|
-
transition:
|
|
65
|
+
transition: color 0.2s ease, background-color 0.2s ease;
|
|
66
66
|
position: relative;
|
|
67
67
|
white-space: nowrap;
|
|
68
68
|
flex-shrink: 0;
|
|
@@ -280,7 +280,8 @@
|
|
|
280
280
|
|
|
281
281
|
/* Reduced motion support */
|
|
282
282
|
@media (prefers-reduced-motion: reduce) {
|
|
283
|
-
.docyard-tabs__tab
|
|
283
|
+
.docyard-tabs__tab,
|
|
284
|
+
.docyard-tabs__indicator {
|
|
284
285
|
transition: none;
|
|
285
286
|
}
|
|
286
287
|
}
|
|
@@ -72,43 +72,52 @@
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
/* Tables */
|
|
75
|
+
.content .table-wrapper {
|
|
76
|
+
margin: var(--space-6) 0;
|
|
77
|
+
overflow-x: auto;
|
|
78
|
+
-webkit-overflow-scrolling: touch;
|
|
79
|
+
border: 1px solid var(--color-border);
|
|
80
|
+
border-radius: var(--radius-lg);
|
|
81
|
+
}
|
|
82
|
+
|
|
75
83
|
.content table {
|
|
76
84
|
width: 100%;
|
|
77
|
-
margin: var(--space-6) 0;
|
|
78
85
|
border-collapse: collapse;
|
|
79
86
|
font-size: var(--font-size-sm);
|
|
80
|
-
|
|
81
|
-
overflow-x: auto;
|
|
82
|
-
border-radius: var(--radius-lg);
|
|
83
|
-
border: 1px solid var(--color-border);
|
|
84
|
-
box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.03);
|
|
87
|
+
margin: 0;
|
|
85
88
|
}
|
|
86
89
|
|
|
87
90
|
.content thead {
|
|
88
|
-
background-color: var(--color-bg-
|
|
91
|
+
background-color: var(--color-bg-tertiary);
|
|
89
92
|
}
|
|
90
93
|
|
|
91
94
|
.content th {
|
|
92
95
|
padding: var(--space-3) var(--space-4);
|
|
93
96
|
text-align: left;
|
|
94
97
|
font-weight: var(--font-weight-semibold);
|
|
95
|
-
border-bottom: 1px solid var(--color-border);
|
|
96
98
|
color: var(--color-text);
|
|
99
|
+
border-bottom: 2px solid var(--color-border);
|
|
100
|
+
white-space: nowrap;
|
|
97
101
|
}
|
|
98
102
|
|
|
99
103
|
.content td {
|
|
100
104
|
padding: var(--space-3) var(--space-4);
|
|
101
|
-
border-bottom: 1px solid var(--color-border
|
|
105
|
+
border-bottom: 1px solid var(--color-border);
|
|
106
|
+
white-space: nowrap;
|
|
102
107
|
}
|
|
103
108
|
|
|
104
|
-
.content tr
|
|
105
|
-
|
|
109
|
+
.content tbody tr {
|
|
110
|
+
transition: background-color var(--transition-fast);
|
|
106
111
|
}
|
|
107
112
|
|
|
108
113
|
.content tbody tr:hover {
|
|
109
114
|
background-color: var(--color-bg-secondary);
|
|
110
115
|
}
|
|
111
116
|
|
|
117
|
+
.content tbody tr:last-child td {
|
|
118
|
+
border-bottom: none;
|
|
119
|
+
}
|
|
120
|
+
|
|
112
121
|
/* Images */
|
|
113
122
|
.content img {
|
|
114
123
|
max-width: 100%;
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
// Docyard Navigation JavaScript
|
|
2
|
+
// Handles sidebar navigation, mobile menu, accordion groups, and scroll behavior
|
|
3
|
+
|
|
4
|
+
(function() {
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
function initMobileMenu() {
|
|
8
|
+
const toggle = document.querySelector('.secondary-header-menu');
|
|
9
|
+
const sidebar = document.querySelector('.sidebar');
|
|
10
|
+
const overlay = document.querySelector('.mobile-overlay');
|
|
11
|
+
|
|
12
|
+
if (!toggle || !sidebar || !overlay) return;
|
|
13
|
+
|
|
14
|
+
function openMenu() {
|
|
15
|
+
sidebar.classList.add('is-open');
|
|
16
|
+
overlay.classList.add('is-visible');
|
|
17
|
+
toggle.setAttribute('aria-expanded', 'true');
|
|
18
|
+
document.body.style.overflow = 'hidden';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function closeMenu() {
|
|
22
|
+
sidebar.classList.remove('is-open');
|
|
23
|
+
overlay.classList.remove('is-visible');
|
|
24
|
+
toggle.setAttribute('aria-expanded', 'false');
|
|
25
|
+
document.body.style.overflow = '';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function toggleMenu() {
|
|
29
|
+
if (sidebar.classList.contains('is-open')) {
|
|
30
|
+
closeMenu();
|
|
31
|
+
} else {
|
|
32
|
+
openMenu();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
toggle.addEventListener('click', toggleMenu);
|
|
37
|
+
overlay.addEventListener('click', closeMenu);
|
|
38
|
+
|
|
39
|
+
document.addEventListener('keydown', function(e) {
|
|
40
|
+
if (e.key === 'Escape' && sidebar.classList.contains('is-open')) {
|
|
41
|
+
closeMenu();
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
sidebar.querySelectorAll('a').forEach(function(link) {
|
|
46
|
+
link.addEventListener('click', closeMenu);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function initAccordion() {
|
|
51
|
+
const toggles = document.querySelectorAll('.nav-group-toggle');
|
|
52
|
+
|
|
53
|
+
toggles.forEach(function(toggle) {
|
|
54
|
+
toggle.addEventListener('click', function() {
|
|
55
|
+
const expanded = toggle.getAttribute('aria-expanded') === 'true';
|
|
56
|
+
const children = toggle.nextElementSibling;
|
|
57
|
+
|
|
58
|
+
if (!children || !children.classList.contains('nav-group-children')) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
toggle.setAttribute('aria-expanded', !expanded);
|
|
63
|
+
children.classList.toggle('collapsed');
|
|
64
|
+
|
|
65
|
+
if (expanded) {
|
|
66
|
+
children.style.maxHeight = '0';
|
|
67
|
+
} else {
|
|
68
|
+
children.style.maxHeight = children.scrollHeight + 'px';
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
document.querySelectorAll('.nav-group-children.collapsed').forEach(function(el) {
|
|
74
|
+
el.style.maxHeight = '0';
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function expandActiveGroups() {
|
|
79
|
+
const activeLinks = document.querySelectorAll('a.active');
|
|
80
|
+
|
|
81
|
+
activeLinks.forEach(function(activeLink) {
|
|
82
|
+
let parent = activeLink.closest('.nav-group-children');
|
|
83
|
+
|
|
84
|
+
while (parent) {
|
|
85
|
+
if (parent.classList.contains('nav-group-children')) {
|
|
86
|
+
parent.classList.remove('collapsed');
|
|
87
|
+
|
|
88
|
+
const toggle = parent.previousElementSibling;
|
|
89
|
+
if (toggle && toggle.classList.contains('nav-group-toggle')) {
|
|
90
|
+
toggle.setAttribute('aria-expanded', 'true');
|
|
91
|
+
|
|
92
|
+
parent.style.maxHeight = 'none';
|
|
93
|
+
const height = parent.scrollHeight;
|
|
94
|
+
parent.style.maxHeight = height + 'px';
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
parent = parent.parentElement?.closest('.nav-group-children');
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function initSidebarScroll() {
|
|
104
|
+
const scrollContainer = document.querySelector('.sidebar nav');
|
|
105
|
+
if (!scrollContainer) return;
|
|
106
|
+
|
|
107
|
+
const STORAGE_KEY = 'docyard_sidebar_scroll';
|
|
108
|
+
const savedPosition = sessionStorage.getItem(STORAGE_KEY);
|
|
109
|
+
|
|
110
|
+
if (savedPosition) {
|
|
111
|
+
const position = parseInt(savedPosition, 10);
|
|
112
|
+
scrollContainer.scrollTop = position;
|
|
113
|
+
|
|
114
|
+
setTimeout(function() {
|
|
115
|
+
scrollContainer.scrollTop = position;
|
|
116
|
+
}, 100);
|
|
117
|
+
} else {
|
|
118
|
+
const activeLink = scrollContainer.querySelector('a.active');
|
|
119
|
+
if (activeLink) {
|
|
120
|
+
setTimeout(function() {
|
|
121
|
+
activeLink.scrollIntoView({
|
|
122
|
+
behavior: 'instant',
|
|
123
|
+
block: 'center'
|
|
124
|
+
});
|
|
125
|
+
}, 50);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
scrollContainer.querySelectorAll('a').forEach(function(link) {
|
|
130
|
+
link.addEventListener('click', function() {
|
|
131
|
+
sessionStorage.setItem(STORAGE_KEY, scrollContainer.scrollTop);
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
let scrollTimeout;
|
|
136
|
+
scrollContainer.addEventListener('scroll', function() {
|
|
137
|
+
clearTimeout(scrollTimeout);
|
|
138
|
+
scrollTimeout = setTimeout(function() {
|
|
139
|
+
sessionStorage.setItem(STORAGE_KEY, scrollContainer.scrollTop);
|
|
140
|
+
}, 150);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
const logo = document.querySelector('.header-logo');
|
|
144
|
+
if (logo) {
|
|
145
|
+
logo.addEventListener('click', function() {
|
|
146
|
+
sessionStorage.removeItem(STORAGE_KEY);
|
|
147
|
+
scrollContainer.scrollTop = 0;
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function initScrollBehavior() {
|
|
153
|
+
const header = document.querySelector('.header');
|
|
154
|
+
const secondaryHeader = document.querySelector('.secondary-header');
|
|
155
|
+
|
|
156
|
+
if (!header || !secondaryHeader) return;
|
|
157
|
+
|
|
158
|
+
let lastScrollTop = 0;
|
|
159
|
+
let ticking = false;
|
|
160
|
+
|
|
161
|
+
function isMobile() {
|
|
162
|
+
return window.innerWidth <= 1024;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function updateHeaders() {
|
|
166
|
+
if (!isMobile()) {
|
|
167
|
+
header.classList.remove('hide-on-scroll');
|
|
168
|
+
secondaryHeader.classList.remove('shift-up');
|
|
169
|
+
ticking = false;
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
|
174
|
+
|
|
175
|
+
if (scrollTop > lastScrollTop && scrollTop > 100) {
|
|
176
|
+
header.classList.add('hide-on-scroll');
|
|
177
|
+
secondaryHeader.classList.add('shift-up');
|
|
178
|
+
} else if (scrollTop < lastScrollTop) {
|
|
179
|
+
header.classList.remove('hide-on-scroll');
|
|
180
|
+
secondaryHeader.classList.remove('shift-up');
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
lastScrollTop = scrollTop <= 0 ? 0 : scrollTop;
|
|
184
|
+
ticking = false;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
window.addEventListener('scroll', function() {
|
|
188
|
+
if (!ticking) {
|
|
189
|
+
window.requestAnimationFrame(updateHeaders);
|
|
190
|
+
ticking = true;
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
window.addEventListener('resize', function() {
|
|
195
|
+
if (!isMobile()) {
|
|
196
|
+
header.classList.remove('hide-on-scroll');
|
|
197
|
+
secondaryHeader.classList.remove('shift-up');
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if ('scrollRestoration' in history) {
|
|
203
|
+
history.scrollRestoration = 'manual';
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (document.readyState === 'loading') {
|
|
207
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
208
|
+
initMobileMenu();
|
|
209
|
+
initAccordion();
|
|
210
|
+
expandActiveGroups();
|
|
211
|
+
initSidebarScroll();
|
|
212
|
+
initScrollBehavior();
|
|
213
|
+
});
|
|
214
|
+
} else {
|
|
215
|
+
initMobileMenu();
|
|
216
|
+
initAccordion();
|
|
217
|
+
expandActiveGroups();
|
|
218
|
+
initSidebarScroll();
|
|
219
|
+
initScrollBehavior();
|
|
220
|
+
}
|
|
221
|
+
})();
|