jekyll-vitepress-theme 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 (80) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +93 -0
  4. data/_includes/doc_footer.html +184 -0
  5. data/_includes/head.html +98 -0
  6. data/_includes/home.html +315 -0
  7. data/_includes/local_nav.html +23 -0
  8. data/_includes/nav.html +232 -0
  9. data/_includes/search.html +14 -0
  10. data/_includes/sidebar.html +47 -0
  11. data/_includes/vp_slots/doc_footer.html +0 -0
  12. data/_includes/vp_slots/head.html +1 -0
  13. data/_includes/vp_slots/layout_bottom.html +0 -0
  14. data/_layouts/default.html +127 -0
  15. data/_layouts/home.html +5 -0
  16. data/assets/css/vitepress-components.css +1524 -0
  17. data/assets/css/vitepress-core.css +2149 -0
  18. data/assets/css/vitepress-overrides.css +1408 -0
  19. data/assets/css/vp-icons.css +24 -0
  20. data/assets/images/favicon/apple-touch-icon.png +0 -0
  21. data/assets/images/favicon/favicon-96x96.png +0 -0
  22. data/assets/images/favicon/favicon.ico +0 -0
  23. data/assets/images/favicon/site.webmanifest +21 -0
  24. data/assets/images/favicon/web-app-manifest-192x192.png +0 -0
  25. data/assets/images/favicon/web-app-manifest-512x512.png +0 -0
  26. data/assets/images/file-icons/css.svg +1 -0
  27. data/assets/images/file-icons/default.svg +1 -0
  28. data/assets/images/file-icons/docker.svg +1 -0
  29. data/assets/images/file-icons/env.svg +1 -0
  30. data/assets/images/file-icons/go.svg +1 -0
  31. data/assets/images/file-icons/html.svg +1 -0
  32. data/assets/images/file-icons/java.svg +1 -0
  33. data/assets/images/file-icons/javascript.svg +1 -0
  34. data/assets/images/file-icons/json.svg +1 -0
  35. data/assets/images/file-icons/kotlin.svg +1 -0
  36. data/assets/images/file-icons/make.svg +1 -0
  37. data/assets/images/file-icons/markdown.svg +1 -0
  38. data/assets/images/file-icons/php.svg +1 -0
  39. data/assets/images/file-icons/python.svg +1 -0
  40. data/assets/images/file-icons/ruby.svg +1 -0
  41. data/assets/images/file-icons/rust.svg +1 -0
  42. data/assets/images/file-icons/shell.svg +1 -0
  43. data/assets/images/file-icons/sql.svg +1 -0
  44. data/assets/images/file-icons/text.svg +1 -0
  45. data/assets/images/file-icons/toml.svg +1 -0
  46. data/assets/images/file-icons/typescript.svg +1 -0
  47. data/assets/images/file-icons/vue.svg +1 -0
  48. data/assets/images/file-icons/xml.svg +1 -0
  49. data/assets/images/file-icons/yaml-dark.svg +1 -0
  50. data/assets/images/file-icons/yaml.svg +1 -0
  51. data/assets/images/logo.svg +337 -0
  52. data/assets/images/social-icons/bitbucket.svg +1 -0
  53. data/assets/images/social-icons/bluesky.svg +1 -0
  54. data/assets/images/social-icons/devdotto.svg +1 -0
  55. data/assets/images/social-icons/discord.svg +1 -0
  56. data/assets/images/social-icons/dribbble.svg +1 -0
  57. data/assets/images/social-icons/facebook.svg +1 -0
  58. data/assets/images/social-icons/github.svg +1 -0
  59. data/assets/images/social-icons/gitlab.svg +1 -0
  60. data/assets/images/social-icons/instagram.svg +1 -0
  61. data/assets/images/social-icons/linkedin.svg +1 -0
  62. data/assets/images/social-icons/mastodon.svg +1 -0
  63. data/assets/images/social-icons/medium.svg +1 -0
  64. data/assets/images/social-icons/npm.svg +1 -0
  65. data/assets/images/social-icons/reddit.svg +1 -0
  66. data/assets/images/social-icons/rss.svg +1 -0
  67. data/assets/images/social-icons/slack.svg +1 -0
  68. data/assets/images/social-icons/stackoverflow.svg +1 -0
  69. data/assets/images/social-icons/telegram.svg +1 -0
  70. data/assets/images/social-icons/twitch.svg +1 -0
  71. data/assets/images/social-icons/twitter.svg +1 -0
  72. data/assets/images/social-icons/x.svg +1 -0
  73. data/assets/images/social-icons/youtube.svg +1 -0
  74. data/assets/images/theme/vitepress-logo-large.svg +340 -0
  75. data/assets/images/theme/vitepress-logo-mini.svg +337 -0
  76. data/assets/js/vitepress-theme.js +1301 -0
  77. data/lib/jekyll/vitepress_theme/hooks.rb +111 -0
  78. data/lib/jekyll/vitepress_theme/version.rb +5 -0
  79. data/lib/jekyll-vitepress-theme.rb +3 -0
  80. metadata +143 -0
@@ -0,0 +1,1301 @@
1
+ (function () {
2
+ 'use strict';
3
+
4
+ var storageKey = 'vitepress-theme-appearance';
5
+ var mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
6
+ var root = document.documentElement;
7
+ var validModes = ['auto', 'dark', 'light'];
8
+
9
+ function normalizeMode(mode) {
10
+ return validModes.indexOf(mode) >= 0 ? mode : 'auto';
11
+ }
12
+
13
+ function readMode() {
14
+ try {
15
+ return normalizeMode(localStorage.getItem(storageKey) || 'auto');
16
+ } catch (error) {
17
+ return 'auto';
18
+ }
19
+ }
20
+
21
+ function writeMode(mode) {
22
+ var normalizedMode = normalizeMode(mode);
23
+ try {
24
+ if (normalizedMode === 'auto') {
25
+ localStorage.removeItem(storageKey);
26
+ } else {
27
+ localStorage.setItem(storageKey, normalizedMode);
28
+ }
29
+ } catch (error) {
30
+ // Ignore storage errors.
31
+ }
32
+ }
33
+
34
+ function getAppearanceLabel(mode, isDark) {
35
+ if (mode === 'dark') {
36
+ return 'Appearance: Dark (forced). Click to force light.';
37
+ }
38
+
39
+ if (mode === 'light') {
40
+ return 'Appearance: Light (forced). Click to follow system.';
41
+ }
42
+
43
+ return isDark
44
+ ? 'Appearance: Auto (system dark). Click to force dark.'
45
+ : 'Appearance: Auto (system light). Click to force dark.';
46
+ }
47
+
48
+ function applyMode(mode) {
49
+ var normalizedMode = normalizeMode(mode);
50
+ var dark = normalizedMode === 'dark' || (normalizedMode === 'auto' && mediaQuery.matches);
51
+ root.classList.toggle('dark', dark);
52
+ root.classList.toggle('light', !dark);
53
+ root.setAttribute('data-appearance-mode', normalizedMode);
54
+
55
+ document.querySelectorAll('.theme-toggle').forEach(function (toggle) {
56
+ toggle.setAttribute('aria-checked', String(dark));
57
+ toggle.setAttribute('data-appearance-mode', normalizedMode);
58
+ toggle.setAttribute('title', getAppearanceLabel(normalizedMode, dark));
59
+ toggle.setAttribute('aria-label', getAppearanceLabel(normalizedMode, dark));
60
+ });
61
+
62
+ window.dispatchEvent(new CustomEvent('vp:appearance-change', { detail: { dark: dark, mode: normalizedMode } }));
63
+ }
64
+
65
+ var mode = readMode();
66
+ applyMode(mode);
67
+
68
+ function cycleMode() {
69
+ if (mode === 'auto') {
70
+ mode = 'dark';
71
+ } else if (mode === 'dark') {
72
+ mode = 'light';
73
+ } else {
74
+ mode = 'auto';
75
+ }
76
+ writeMode(mode);
77
+ applyMode(mode);
78
+ }
79
+
80
+ document.querySelectorAll('.theme-toggle').forEach(function (toggle) {
81
+ toggle.addEventListener('click', function (event) {
82
+ if (event.altKey) {
83
+ mode = 'auto';
84
+ writeMode(mode);
85
+ applyMode(mode);
86
+ return;
87
+ }
88
+
89
+ cycleMode();
90
+ });
91
+ });
92
+
93
+ if (typeof mediaQuery.addEventListener === 'function') {
94
+ mediaQuery.addEventListener('change', function () {
95
+ if (mode === 'auto') {
96
+ applyMode('auto');
97
+ }
98
+ });
99
+ }
100
+
101
+ window.__vpAppearance = {
102
+ getMode: function () {
103
+ return mode;
104
+ },
105
+ setMode: function (nextMode) {
106
+ mode = normalizeMode(nextMode);
107
+ writeMode(mode);
108
+ applyMode(mode);
109
+ },
110
+ clearMode: function () {
111
+ mode = 'auto';
112
+ writeMode(mode);
113
+ applyMode(mode);
114
+ }
115
+ };
116
+
117
+ var navBar = document.getElementById('vp-nav-bar');
118
+ var sidebar = document.getElementById('vp-sidebar');
119
+ var backdrop = document.getElementById('vp-backdrop');
120
+ var hamburger = document.getElementById('vp-nav-hamburger');
121
+ var localMenuButton = document.getElementById('vp-local-menu-button');
122
+ var navScreen = document.getElementById('VPNavScreen');
123
+ var versionSelector = document.getElementById('vp-version-selector');
124
+ var versionButton = document.getElementById('vp-version-button');
125
+ var versionMenu = document.getElementById('vp-version-menu');
126
+
127
+ var menuOpen = false;
128
+ var versionOpen = false;
129
+
130
+ function setVersionOpen(open) {
131
+ if (!versionSelector || !versionButton || !versionMenu) {
132
+ versionOpen = false;
133
+ return;
134
+ }
135
+
136
+ versionOpen = open;
137
+ versionSelector.classList.toggle('open', open);
138
+ versionButton.setAttribute('aria-expanded', String(open));
139
+ versionMenu.hidden = !open;
140
+ }
141
+
142
+ if (versionButton && versionMenu) {
143
+ versionButton.addEventListener('click', function (event) {
144
+ event.preventDefault();
145
+ event.stopPropagation();
146
+ setVersionOpen(!versionOpen);
147
+ });
148
+
149
+ versionMenu.addEventListener('click', function (event) {
150
+ if (event.target.closest('a')) {
151
+ setVersionOpen(false);
152
+ }
153
+ });
154
+
155
+ document.addEventListener('click', function (event) {
156
+ if (versionOpen && versionSelector && !versionSelector.contains(event.target)) {
157
+ setVersionOpen(false);
158
+ }
159
+ });
160
+ }
161
+
162
+ function setMenuOpen(open) {
163
+ menuOpen = open;
164
+
165
+ if (open && versionOpen) {
166
+ setVersionOpen(false);
167
+ }
168
+
169
+ if (sidebar) {
170
+ sidebar.classList.toggle('open', open);
171
+ }
172
+
173
+ if (navBar) {
174
+ navBar.classList.toggle('screen-open', open);
175
+ }
176
+
177
+ if (backdrop) {
178
+ backdrop.classList.toggle('is-active', open);
179
+ }
180
+
181
+ if (hamburger) {
182
+ hamburger.classList.toggle('active', open);
183
+ hamburger.setAttribute('aria-expanded', String(open));
184
+ }
185
+
186
+ if (localMenuButton) {
187
+ localMenuButton.setAttribute('aria-expanded', String(open));
188
+ }
189
+
190
+ if (navScreen) {
191
+ navScreen.hidden = !open;
192
+ }
193
+
194
+ document.body.classList.toggle('vp-nav-screen-open', open);
195
+ }
196
+
197
+ function toggleMenu() {
198
+ setMenuOpen(!menuOpen);
199
+ }
200
+
201
+ if (hamburger) {
202
+ hamburger.addEventListener('click', toggleMenu);
203
+ }
204
+
205
+ if (localMenuButton) {
206
+ localMenuButton.addEventListener('click', toggleMenu);
207
+ }
208
+
209
+ if (backdrop) {
210
+ backdrop.addEventListener('click', function () {
211
+ setMenuOpen(false);
212
+ });
213
+ }
214
+
215
+ if (navScreen) {
216
+ navScreen.addEventListener('click', function (event) {
217
+ if (event.target === navScreen || event.target.closest('a')) {
218
+ setMenuOpen(false);
219
+ }
220
+ });
221
+ }
222
+
223
+ window.addEventListener('resize', function () {
224
+ if (window.innerWidth >= 768 && menuOpen) {
225
+ setMenuOpen(false);
226
+ }
227
+ if (window.innerWidth < 768 && versionOpen) {
228
+ setVersionOpen(false);
229
+ }
230
+ });
231
+
232
+ function syncNavTop() {
233
+ if (!navBar) {
234
+ return;
235
+ }
236
+ navBar.classList.toggle('top', window.scrollY < 4);
237
+ }
238
+
239
+ syncNavTop();
240
+ window.addEventListener('scroll', syncNavTop, { passive: true });
241
+
242
+ document.querySelectorAll('.VPSidebarItem.level-0.collapsible').forEach(function (section) {
243
+ var item = section.querySelector(':scope > .item');
244
+ var caret = section.querySelector(':scope > .item .caret');
245
+
246
+ function toggleSection() {
247
+ section.classList.toggle('collapsed');
248
+ }
249
+
250
+ if (item) {
251
+ item.addEventListener('click', function (event) {
252
+ if (event.target.closest('a')) {
253
+ return;
254
+ }
255
+ toggleSection();
256
+ });
257
+
258
+ item.addEventListener('keydown', function (event) {
259
+ if (event.key === 'Enter' || event.key === ' ') {
260
+ event.preventDefault();
261
+ toggleSection();
262
+ }
263
+ });
264
+ }
265
+
266
+ if (caret) {
267
+ caret.addEventListener('click', function (event) {
268
+ event.stopPropagation();
269
+ toggleSection();
270
+ });
271
+ caret.addEventListener('keydown', function (event) {
272
+ if (event.key === 'Enter' || event.key === ' ') {
273
+ event.preventDefault();
274
+ event.stopPropagation();
275
+ toggleSection();
276
+ }
277
+ });
278
+ }
279
+ });
280
+
281
+ var searchRoot = document.getElementById('vp-search');
282
+ var searchButton = document.getElementById('vp-search-button');
283
+ var searchBackdrop = document.getElementById('vp-search-backdrop');
284
+ var searchInput = document.getElementById('vp-search-input');
285
+ var searchResults = document.getElementById('vp-search-results');
286
+ var searchIndexUrl = searchRoot ? searchRoot.getAttribute('data-search-index-url') : null;
287
+
288
+ var searchOpen = false;
289
+ var searchItems = [];
290
+ var searchIndexPromise = null;
291
+ var activeResultIndex = -1;
292
+
293
+ function loadSearchIndex() {
294
+ if (!searchIndexUrl) {
295
+ return Promise.resolve([]);
296
+ }
297
+
298
+ if (searchItems.length > 0) {
299
+ return Promise.resolve(searchItems);
300
+ }
301
+
302
+ if (searchIndexPromise) {
303
+ return searchIndexPromise;
304
+ }
305
+
306
+ searchIndexPromise = fetch(searchIndexUrl, { credentials: 'same-origin' })
307
+ .then(function (response) {
308
+ if (!response.ok) {
309
+ throw new Error('Search index load failed');
310
+ }
311
+ return response.json();
312
+ })
313
+ .then(function (items) {
314
+ if (Array.isArray(items)) {
315
+ searchItems = items;
316
+ }
317
+ return searchItems;
318
+ })
319
+ .catch(function () {
320
+ searchItems = [];
321
+ return searchItems;
322
+ });
323
+
324
+ return searchIndexPromise;
325
+ }
326
+
327
+ function escapeHtml(value) {
328
+ return String(value || '')
329
+ .replace(/&/g, '&amp;')
330
+ .replace(/</g, '&lt;')
331
+ .replace(/>/g, '&gt;')
332
+ .replace(/"/g, '&quot;')
333
+ .replace(/'/g, '&#039;');
334
+ }
335
+
336
+ function scoreSearchItem(item, terms, query) {
337
+ var title = String(item.title || '').toLowerCase();
338
+ var content = String(item.content || '').toLowerCase();
339
+
340
+ var score = 0;
341
+ for (var i = 0; i < terms.length; i += 1) {
342
+ var term = terms[i];
343
+ var titleIndex = title.indexOf(term);
344
+ var contentIndex = content.indexOf(term);
345
+
346
+ if (titleIndex < 0 && contentIndex < 0) {
347
+ return -1;
348
+ }
349
+
350
+ if (titleIndex >= 0) {
351
+ score += titleIndex === 0 ? 100 : 40;
352
+ }
353
+
354
+ if (contentIndex >= 0) {
355
+ score += contentIndex < 120 ? 20 : 10;
356
+ }
357
+ }
358
+
359
+ if (title.indexOf(query) >= 0) {
360
+ score += 60;
361
+ }
362
+
363
+ return score;
364
+ }
365
+
366
+ function buildSnippet(item, terms) {
367
+ var content = String(item.content || '').replace(/\s+/g, ' ').trim();
368
+ if (!content) {
369
+ return '';
370
+ }
371
+
372
+ var lower = content.toLowerCase();
373
+ var index = -1;
374
+
375
+ for (var i = 0; i < terms.length; i += 1) {
376
+ var hit = lower.indexOf(terms[i]);
377
+ if (hit >= 0 && (index < 0 || hit < index)) {
378
+ index = hit;
379
+ }
380
+ }
381
+
382
+ if (index < 0) {
383
+ index = 0;
384
+ }
385
+
386
+ var start = Math.max(0, index - 60);
387
+ var end = Math.min(content.length, start + 180);
388
+ var snippet = content.slice(start, end).trim();
389
+
390
+ if (start > 0) {
391
+ snippet = '... ' + snippet;
392
+ }
393
+
394
+ if (end < content.length) {
395
+ snippet += ' ...';
396
+ }
397
+
398
+ return snippet;
399
+ }
400
+
401
+ function setActiveSearchResult(index) {
402
+ if (!searchResults) {
403
+ return;
404
+ }
405
+
406
+ var links = Array.from(searchResults.querySelectorAll('.VPSearchResult'));
407
+ if (!links.length) {
408
+ activeResultIndex = -1;
409
+ return;
410
+ }
411
+
412
+ activeResultIndex = Math.max(0, Math.min(index, links.length - 1));
413
+
414
+ links.forEach(function (link, linkIndex) {
415
+ var active = linkIndex === activeResultIndex;
416
+ link.classList.toggle('active', active);
417
+ if (active) {
418
+ link.scrollIntoView({ block: 'nearest' });
419
+ }
420
+ });
421
+ }
422
+
423
+ function renderSearchResults(query) {
424
+ if (!searchResults) {
425
+ return;
426
+ }
427
+
428
+ var normalized = String(query || '').trim().toLowerCase();
429
+
430
+ if (!normalized) {
431
+ searchResults.innerHTML = '<p class="VPSearchEmpty">Type to search documentation</p>';
432
+ activeResultIndex = -1;
433
+ return;
434
+ }
435
+
436
+ var terms = normalized.split(/\s+/).filter(Boolean);
437
+
438
+ var ranked = searchItems
439
+ .map(function (item) {
440
+ return {
441
+ item: item,
442
+ score: scoreSearchItem(item, terms, normalized)
443
+ };
444
+ })
445
+ .filter(function (entry) {
446
+ return entry.score >= 0;
447
+ })
448
+ .sort(function (a, b) {
449
+ return b.score - a.score;
450
+ })
451
+ .slice(0, 20);
452
+
453
+ if (!ranked.length) {
454
+ searchResults.innerHTML = '<p class="VPSearchEmpty">No matches found</p>';
455
+ activeResultIndex = -1;
456
+ return;
457
+ }
458
+
459
+ var html = ranked
460
+ .map(function (entry) {
461
+ var item = entry.item;
462
+ var title = escapeHtml(item.title || item.url || 'Untitled');
463
+ var url = escapeHtml(item.url || '/');
464
+ var snippet = escapeHtml(buildSnippet(item, terms));
465
+
466
+ return (
467
+ '<a class="VPSearchResult" role="option" href="' +
468
+ url +
469
+ '">' +
470
+ '<span class="title">' +
471
+ title +
472
+ '</span>' +
473
+ '<span class="snippet">' +
474
+ snippet +
475
+ '</span>' +
476
+ '</a>'
477
+ );
478
+ })
479
+ .join('');
480
+
481
+ searchResults.innerHTML = html;
482
+ setActiveSearchResult(0);
483
+ }
484
+
485
+ function closeSearch() {
486
+ if (!searchRoot) {
487
+ return;
488
+ }
489
+
490
+ searchOpen = false;
491
+ searchRoot.hidden = true;
492
+ document.body.classList.remove('vp-search-open');
493
+
494
+ if (searchButton) {
495
+ searchButton.setAttribute('aria-expanded', 'false');
496
+ }
497
+ }
498
+
499
+ function openSearch() {
500
+ if (!searchRoot || !searchInput) {
501
+ return;
502
+ }
503
+
504
+ if (versionOpen) {
505
+ setVersionOpen(false);
506
+ }
507
+
508
+ if (menuOpen) {
509
+ setMenuOpen(false);
510
+ }
511
+
512
+ searchOpen = true;
513
+ searchRoot.hidden = false;
514
+ document.body.classList.add('vp-search-open');
515
+
516
+ if (searchButton) {
517
+ searchButton.setAttribute('aria-expanded', 'true');
518
+ }
519
+
520
+ loadSearchIndex().then(function () {
521
+ renderSearchResults(searchInput.value);
522
+ });
523
+
524
+ window.requestAnimationFrame(function () {
525
+ searchInput.focus();
526
+ searchInput.select();
527
+ });
528
+ }
529
+
530
+ if (searchButton) {
531
+ searchButton.addEventListener('click', function () {
532
+ if (searchOpen) {
533
+ closeSearch();
534
+ } else {
535
+ openSearch();
536
+ }
537
+ });
538
+ }
539
+
540
+ if (searchBackdrop) {
541
+ searchBackdrop.addEventListener('click', closeSearch);
542
+ }
543
+
544
+ if (searchResults) {
545
+ searchResults.addEventListener('click', function (event) {
546
+ if (event.target.closest('a')) {
547
+ closeSearch();
548
+ }
549
+ });
550
+ }
551
+
552
+ if (searchInput) {
553
+ searchInput.addEventListener('input', function (event) {
554
+ renderSearchResults(event.target.value);
555
+ });
556
+
557
+ searchInput.addEventListener('keydown', function (event) {
558
+ if (event.key === 'ArrowDown') {
559
+ event.preventDefault();
560
+ setActiveSearchResult(activeResultIndex + 1);
561
+ return;
562
+ }
563
+
564
+ if (event.key === 'ArrowUp') {
565
+ event.preventDefault();
566
+ setActiveSearchResult(activeResultIndex - 1);
567
+ return;
568
+ }
569
+
570
+ if (event.key === 'Enter') {
571
+ var links = searchResults ? Array.from(searchResults.querySelectorAll('.VPSearchResult')) : [];
572
+ if (links.length && activeResultIndex >= 0) {
573
+ window.location.href = links[activeResultIndex].getAttribute('href');
574
+ }
575
+ }
576
+ });
577
+ }
578
+
579
+ function shouldOpenSearchFromKeyboard(event) {
580
+ if (event.defaultPrevented || event.metaKey || event.ctrlKey || event.altKey || event.shiftKey) {
581
+ return false;
582
+ }
583
+
584
+ var target = event.target;
585
+ if (!target) {
586
+ return true;
587
+ }
588
+
589
+ var tagName = String(target.tagName || '').toLowerCase();
590
+ if (tagName === 'input' || tagName === 'textarea' || tagName === 'select') {
591
+ return false;
592
+ }
593
+
594
+ if (target.isContentEditable) {
595
+ return false;
596
+ }
597
+
598
+ return event.key === '/';
599
+ }
600
+
601
+ document.addEventListener('keydown', function (event) {
602
+ if (event.key === 'Escape') {
603
+ if (searchOpen) {
604
+ event.preventDefault();
605
+ closeSearch();
606
+ return;
607
+ }
608
+
609
+ if (versionOpen) {
610
+ event.preventDefault();
611
+ setVersionOpen(false);
612
+ return;
613
+ }
614
+
615
+ setMenuOpen(false);
616
+ return;
617
+ }
618
+
619
+ var isSearchShortcut = (event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 'k';
620
+ if (isSearchShortcut) {
621
+ event.preventDefault();
622
+ if (versionOpen) {
623
+ setVersionOpen(false);
624
+ }
625
+ openSearch();
626
+ return;
627
+ }
628
+
629
+ if (shouldOpenSearchFromKeyboard(event)) {
630
+ event.preventDefault();
631
+ if (versionOpen) {
632
+ setVersionOpen(false);
633
+ }
634
+ openSearch();
635
+ }
636
+ });
637
+
638
+ function writeToClipboard(text) {
639
+ if (navigator.clipboard && typeof navigator.clipboard.writeText === 'function') {
640
+ return navigator.clipboard.writeText(text);
641
+ }
642
+
643
+ return new Promise(function (resolve, reject) {
644
+ try {
645
+ var textarea = document.createElement('textarea');
646
+ textarea.value = text;
647
+ textarea.setAttribute('readonly', '');
648
+ textarea.style.position = 'fixed';
649
+ textarea.style.top = '-9999px';
650
+ document.body.appendChild(textarea);
651
+ textarea.select();
652
+
653
+ var copied = document.execCommand('copy');
654
+ document.body.removeChild(textarea);
655
+
656
+ if (copied) {
657
+ resolve();
658
+ } else {
659
+ reject(new Error('Copy command failed'));
660
+ }
661
+ } catch (error) {
662
+ reject(error);
663
+ }
664
+ });
665
+ }
666
+
667
+ var fileIconAliases = {
668
+ rb: 'ruby',
669
+ rake: 'ruby',
670
+ erb: 'ruby',
671
+ ruby: 'ruby',
672
+
673
+ js: 'javascript',
674
+ mjs: 'javascript',
675
+ cjs: 'javascript',
676
+ jsx: 'javascript',
677
+ javascript: 'javascript',
678
+
679
+ ts: 'typescript',
680
+ mts: 'typescript',
681
+ cts: 'typescript',
682
+ tsx: 'typescript',
683
+ typescript: 'typescript',
684
+
685
+ json: 'json',
686
+ jsonc: 'json',
687
+ json5: 'json',
688
+
689
+ md: 'markdown',
690
+ markdown: 'markdown',
691
+ mdx: 'markdown',
692
+
693
+ html: 'html',
694
+ htm: 'html',
695
+
696
+ css: 'css',
697
+ scss: 'css',
698
+ sass: 'css',
699
+ less: 'css',
700
+
701
+ vue: 'vue',
702
+ yml: 'yaml',
703
+ yaml: 'yaml',
704
+ toml: 'toml',
705
+
706
+ sh: 'shell',
707
+ bash: 'shell',
708
+ zsh: 'shell',
709
+ fish: 'shell',
710
+ shell: 'shell',
711
+
712
+ py: 'python',
713
+ python: 'python',
714
+
715
+ go: 'go',
716
+ golang: 'go',
717
+ rs: 'rust',
718
+ rust: 'rust',
719
+ java: 'java',
720
+
721
+ kt: 'kotlin',
722
+ kts: 'kotlin',
723
+ kotlin: 'kotlin',
724
+
725
+ php: 'php',
726
+ sql: 'sql',
727
+ xml: 'xml',
728
+
729
+ docker: 'docker',
730
+ dockerfile: 'docker',
731
+ containerfile: 'docker',
732
+
733
+ make: 'make',
734
+ makefile: 'make',
735
+
736
+ env: 'env',
737
+ '.env': 'env',
738
+
739
+ txt: 'text',
740
+ text: 'text',
741
+ plaintext: 'text'
742
+ };
743
+
744
+ var specialFileIconAliases = {
745
+ gemfile: 'ruby',
746
+ rakefile: 'ruby',
747
+ '.ruby-version': 'ruby',
748
+ dockerfile: 'docker',
749
+ containerfile: 'docker',
750
+ makefile: 'make',
751
+ '.env': 'env'
752
+ };
753
+
754
+ function normalizeFileIconKey(value) {
755
+ var key = (value || '').toLowerCase().trim();
756
+ return fileIconAliases[key] || '';
757
+ }
758
+
759
+ function inferFileIconFromTitle(title) {
760
+ var raw = (title || '').trim().toLowerCase();
761
+ if (!raw) {
762
+ return '';
763
+ }
764
+
765
+ var clean = raw.split(/[?#]/)[0];
766
+ var base = clean.split('/').pop();
767
+ if (!base) {
768
+ return '';
769
+ }
770
+
771
+ var directMatch = specialFileIconAliases[base];
772
+ if (directMatch) {
773
+ return directMatch;
774
+ }
775
+
776
+ if (base.indexOf('.env.') === 0) {
777
+ return 'env';
778
+ }
779
+
780
+ var dotIndex = base.lastIndexOf('.');
781
+ if (dotIndex > 0 && dotIndex < base.length - 1) {
782
+ var ext = base.slice(dotIndex + 1);
783
+ return normalizeFileIconKey(ext);
784
+ }
785
+
786
+ return normalizeFileIconKey(base);
787
+ }
788
+
789
+ function inferFileIconFromLanguage(language) {
790
+ return normalizeFileIconKey(language);
791
+ }
792
+
793
+ function addCopyButtons() {
794
+ document.querySelectorAll('.vp-doc div.highlighter-rouge').forEach(function (block) {
795
+ var code = block.querySelector('pre code');
796
+ if (!code) {
797
+ return;
798
+ }
799
+
800
+ var button = block.querySelector(':scope > button.copy');
801
+ if (!button) {
802
+ button = document.createElement('button');
803
+ button.className = 'copy';
804
+ button.type = 'button';
805
+ block.insertBefore(button, block.firstChild);
806
+ }
807
+ button.setAttribute('aria-label', 'Copy code');
808
+ button.setAttribute('title', 'Copy code');
809
+
810
+ var language = '';
811
+ Array.from(block.classList).forEach(function (className) {
812
+ if (!language && className.indexOf('language-') === 0) {
813
+ language = className.slice(9).trim().toLowerCase();
814
+ }
815
+ });
816
+ if (language === 'plaintext') {
817
+ language = 'text';
818
+ }
819
+
820
+ var languageTag = block.querySelector(':scope > span.lang');
821
+ if (!languageTag && language) {
822
+ languageTag = document.createElement('span');
823
+ languageTag.className = 'lang';
824
+ languageTag.textContent = language;
825
+ if (button.nextSibling) {
826
+ block.insertBefore(languageTag, button.nextSibling);
827
+ } else {
828
+ block.appendChild(languageTag);
829
+ }
830
+ }
831
+
832
+ var title = block.getAttribute('data-title') || '';
833
+ if (!title) {
834
+ var previous = block.previousElementSibling;
835
+ if (previous && previous.classList.contains('vp-code-title')) {
836
+ title = previous.textContent ? previous.textContent.trim() : '';
837
+ previous.remove();
838
+ }
839
+ }
840
+
841
+ if (title && (!block.parentElement || !block.parentElement.classList.contains('vp-code-block-title'))) {
842
+ var wrapper = document.createElement('div');
843
+ wrapper.className = 'vp-code-block-title';
844
+
845
+ var iconKey = inferFileIconFromTitle(title) || inferFileIconFromLanguage(language) || 'default';
846
+ var titleBar = document.createElement('div');
847
+ titleBar.className = 'vp-code-block-title-bar';
848
+
849
+ var titleText = document.createElement('span');
850
+ titleText.className = 'vp-code-block-title-text';
851
+ titleText.setAttribute('data-title', title);
852
+ if (iconKey) {
853
+ titleText.setAttribute('data-icon', iconKey);
854
+ }
855
+ titleText.textContent = title;
856
+
857
+ titleBar.appendChild(titleText);
858
+
859
+ var parent = block.parentNode;
860
+ if (parent) {
861
+ parent.insertBefore(wrapper, block);
862
+ wrapper.appendChild(titleBar);
863
+ wrapper.appendChild(block);
864
+ block.classList.add('has-title');
865
+ }
866
+ }
867
+
868
+ button.addEventListener('click', function () {
869
+ var text = code.textContent || '';
870
+
871
+ writeToClipboard(text)
872
+ .then(function () {
873
+ button.classList.add('copied');
874
+ if (button._copyTimeout) {
875
+ window.clearTimeout(button._copyTimeout);
876
+ }
877
+ button._copyTimeout = window.setTimeout(function () {
878
+ button.classList.remove('copied');
879
+ }, 2000);
880
+ })
881
+ .catch(function () {
882
+ // Ignore copy errors so UI remains interactive.
883
+ });
884
+ });
885
+ });
886
+ }
887
+
888
+ addCopyButtons();
889
+
890
+ var content = document.querySelector('.vp-doc');
891
+ if (!content) {
892
+ return;
893
+ }
894
+
895
+ content.querySelectorAll('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]').forEach(function (heading) {
896
+ if (heading.querySelector('.header-anchor')) {
897
+ return;
898
+ }
899
+
900
+ var title = heading.textContent ? heading.textContent.trim() : heading.id;
901
+ var anchor = document.createElement('a');
902
+ anchor.className = 'header-anchor';
903
+ anchor.href = '#' + heading.id;
904
+ anchor.setAttribute('aria-label', 'Permalink to "' + title + '"');
905
+ anchor.textContent = '\u200B';
906
+
907
+ heading.appendChild(document.createTextNode(' '));
908
+ heading.appendChild(anchor);
909
+ });
910
+
911
+ var headings = Array.from(content.querySelectorAll('h2[id], h3[id]'));
912
+ var asideOutline = document.querySelector('.VPDocAsideOutline');
913
+ var localNav = document.getElementById('vp-local-nav');
914
+ var localOutlineDropdown = document.getElementById('vp-local-outline-dropdown');
915
+
916
+ var localOutlineButton = document.getElementById('vp-local-outline-button');
917
+ var localOutlineItems = document.querySelector('#vp-local-outline-dropdown .items');
918
+ var localOutlineContainer = document.querySelector('#vp-local-outline-dropdown .outline .VPDocOutlineItem');
919
+ var localTopLink = document.getElementById('vp-local-top-link');
920
+ var returnToTopLabel = (localTopLink && localTopLink.textContent ? localTopLink.textContent.trim() : 'Return to top');
921
+
922
+ function syncLocalOutlineViewportHeight() {
923
+ if (!localOutlineDropdown) {
924
+ return;
925
+ }
926
+
927
+ var viewportHeight = window.innerHeight;
928
+ if (window.visualViewport && window.visualViewport.height) {
929
+ viewportHeight = window.visualViewport.height;
930
+ }
931
+
932
+ localOutlineDropdown.style.setProperty('--vp-vh', String(Math.round(viewportHeight)) + 'px');
933
+ }
934
+
935
+ syncLocalOutlineViewportHeight();
936
+ window.addEventListener('resize', syncLocalOutlineViewportHeight, { passive: true });
937
+ if (window.visualViewport && typeof window.visualViewport.addEventListener === 'function') {
938
+ window.visualViewport.addEventListener('resize', syncLocalOutlineViewportHeight, { passive: true });
939
+ }
940
+
941
+ function createOutlineTree(list) {
942
+ var tree = [];
943
+ var currentGroup = null;
944
+
945
+ list.forEach(function (heading) {
946
+ if (heading.tagName === 'H2') {
947
+ currentGroup = {
948
+ heading: heading,
949
+ children: []
950
+ };
951
+ tree.push(currentGroup);
952
+ return;
953
+ }
954
+
955
+ if (!currentGroup) {
956
+ currentGroup = {
957
+ heading: heading,
958
+ children: []
959
+ };
960
+ tree.push(currentGroup);
961
+ return;
962
+ }
963
+
964
+ currentGroup.children.push({
965
+ heading: heading,
966
+ children: []
967
+ });
968
+ });
969
+
970
+ return tree;
971
+ }
972
+
973
+ function buildOutlineNodes(entries, isRoot) {
974
+ var ul = document.createElement('ul');
975
+ ul.className = 'VPDocOutlineItem ' + (isRoot ? 'root' : 'nested');
976
+
977
+ entries.forEach(function (entry) {
978
+ if (!entry.heading) {
979
+ return;
980
+ }
981
+
982
+ var li = document.createElement('li');
983
+ var link = document.createElement('a');
984
+ var label = entry.heading.textContent ? entry.heading.textContent.trim() : entry.heading.id;
985
+
986
+ link.className = 'outline-link';
987
+ link.href = '#' + entry.heading.id;
988
+ link.title = label;
989
+ link.textContent = label;
990
+
991
+ li.appendChild(link);
992
+
993
+ if (entry.children && entry.children.length) {
994
+ li.appendChild(buildOutlineNodes(entry.children, false));
995
+ }
996
+
997
+ ul.appendChild(li);
998
+ });
999
+
1000
+ return ul;
1001
+ }
1002
+
1003
+ function replaceOutline(selector, tree, isRoot) {
1004
+ var target = document.querySelector(selector);
1005
+ if (!target) {
1006
+ return;
1007
+ }
1008
+
1009
+ target.innerHTML = '';
1010
+ var outline = buildOutlineNodes(tree, isRoot);
1011
+
1012
+ while (outline.firstChild) {
1013
+ target.appendChild(outline.firstChild);
1014
+ }
1015
+ }
1016
+
1017
+ var hasOutline = headings.length > 0;
1018
+
1019
+ if (!hasOutline) {
1020
+ if (asideOutline) {
1021
+ asideOutline.classList.remove('has-outline');
1022
+ }
1023
+
1024
+ if (localNav) {
1025
+ localNav.classList.add('empty');
1026
+ }
1027
+
1028
+ if (localOutlineButton) {
1029
+ var text = localOutlineButton.querySelector('.menu-text');
1030
+ var icon = localOutlineButton.querySelector('.icon');
1031
+ if (text) {
1032
+ text.textContent = returnToTopLabel;
1033
+ }
1034
+ if (icon) {
1035
+ icon.style.display = 'none';
1036
+ }
1037
+ }
1038
+ } else {
1039
+ var tree = createOutlineTree(headings);
1040
+ replaceOutline('.VPDocAsideOutline .VPDocOutlineItem.root', tree, true);
1041
+ replaceOutline('#vp-local-outline-dropdown .outline .VPDocOutlineItem', tree, true);
1042
+ }
1043
+
1044
+ var localOutlineOpen = false;
1045
+
1046
+ function closeLocalOutline() {
1047
+ localOutlineOpen = false;
1048
+ if (localOutlineItems) {
1049
+ localOutlineItems.hidden = true;
1050
+ }
1051
+ if (localOutlineButton) {
1052
+ localOutlineButton.classList.remove('open');
1053
+ localOutlineButton.setAttribute('aria-expanded', 'false');
1054
+ }
1055
+ }
1056
+
1057
+ if (localOutlineButton) {
1058
+ localOutlineButton.setAttribute('aria-expanded', 'false');
1059
+
1060
+ localOutlineButton.addEventListener('click', function () {
1061
+ if (!hasOutline) {
1062
+ window.scrollTo({ top: 0, left: 0, behavior: 'smooth' });
1063
+ return;
1064
+ }
1065
+
1066
+ localOutlineOpen = !localOutlineOpen;
1067
+ if (localOutlineItems) {
1068
+ localOutlineItems.hidden = !localOutlineOpen;
1069
+ }
1070
+ localOutlineButton.classList.toggle('open', localOutlineOpen);
1071
+ localOutlineButton.setAttribute('aria-expanded', String(localOutlineOpen));
1072
+ });
1073
+ }
1074
+
1075
+ if (localTopLink) {
1076
+ localTopLink.addEventListener('click', function (event) {
1077
+ event.preventDefault();
1078
+ closeLocalOutline();
1079
+ window.scrollTo({ top: 0, left: 0, behavior: 'smooth' });
1080
+ });
1081
+ }
1082
+
1083
+ document.addEventListener('click', function (event) {
1084
+ if (!localOutlineDropdown || !localOutlineOpen) {
1085
+ return;
1086
+ }
1087
+ if (!localOutlineDropdown.contains(event.target)) {
1088
+ closeLocalOutline();
1089
+ }
1090
+ });
1091
+
1092
+ if (localOutlineContainer) {
1093
+ localOutlineContainer.addEventListener('click', function (event) {
1094
+ if (event.target.classList.contains('outline-link')) {
1095
+ closeLocalOutline();
1096
+ }
1097
+ });
1098
+ }
1099
+
1100
+ var marker = document.getElementById('vp-outline-marker');
1101
+
1102
+ function getConfiguredScrollOffset() {
1103
+ var bodyScrollOffset = document.body ? document.body.getAttribute('data-vp-scroll-offset') : null;
1104
+ var offset = bodyScrollOffset ? parseFloat(bodyScrollOffset) : NaN;
1105
+ if (!Number.isNaN(offset)) {
1106
+ return offset;
1107
+ }
1108
+ return 134;
1109
+ }
1110
+
1111
+ function scrollToHashWithOffset(hash, smooth) {
1112
+ if (!hash) {
1113
+ return;
1114
+ }
1115
+
1116
+ var target = null;
1117
+ try {
1118
+ target = document.getElementById(decodeURIComponent(hash).slice(1));
1119
+ } catch (error) {
1120
+ target = null;
1121
+ }
1122
+
1123
+ if (!target) {
1124
+ return;
1125
+ }
1126
+
1127
+ var targetTop = window.scrollY +
1128
+ target.getBoundingClientRect().top -
1129
+ getConfiguredScrollOffset() +
1130
+ (parseInt(window.getComputedStyle(target).paddingTop, 10) || 0);
1131
+
1132
+ var reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
1133
+ var behavior = 'auto';
1134
+ if (!reduceMotion && smooth && Math.abs(targetTop - window.scrollY) <= window.innerHeight) {
1135
+ behavior = 'smooth';
1136
+ }
1137
+
1138
+ window.scrollTo({ left: 0, top: targetTop, behavior: behavior });
1139
+
1140
+ target.focus({ preventScroll: true });
1141
+ if (document.activeElement === target || target.hasAttribute('tabindex')) {
1142
+ return;
1143
+ }
1144
+
1145
+ var restoreTabindex = function () {
1146
+ target.removeAttribute('tabindex');
1147
+ target.removeEventListener('blur', restoreTabindex);
1148
+ };
1149
+
1150
+ target.setAttribute('tabindex', '-1');
1151
+ target.addEventListener('blur', restoreTabindex);
1152
+ target.focus({ preventScroll: true });
1153
+ if (document.activeElement !== target) {
1154
+ restoreTabindex();
1155
+ }
1156
+ }
1157
+
1158
+ function handleOutlineLinkClick(event) {
1159
+ var link = event.currentTarget;
1160
+ if (!link) {
1161
+ return;
1162
+ }
1163
+
1164
+ var hash = link.getAttribute('href');
1165
+ if (!hash || hash.charAt(0) !== '#') {
1166
+ return;
1167
+ }
1168
+
1169
+ event.preventDefault();
1170
+
1171
+ if (window.history && typeof window.history.pushState === 'function') {
1172
+ window.history.pushState(null, '', hash);
1173
+ } else {
1174
+ window.location.hash = hash;
1175
+ }
1176
+
1177
+ scrollToHashWithOffset(hash, true);
1178
+ }
1179
+
1180
+ document.querySelectorAll('.outline-link').forEach(function (link) {
1181
+ link.addEventListener('click', handleOutlineLinkClick);
1182
+ });
1183
+
1184
+ if (window.location.hash) {
1185
+ window.requestAnimationFrame(function () {
1186
+ scrollToHashWithOffset(window.location.hash, false);
1187
+ });
1188
+ }
1189
+
1190
+ window.addEventListener('hashchange', function () {
1191
+ if (window.location.hash) {
1192
+ scrollToHashWithOffset(window.location.hash, false);
1193
+ }
1194
+ });
1195
+
1196
+ function getAbsoluteTop(element) {
1197
+ var offsetTop = 0;
1198
+ var current = element;
1199
+
1200
+ while (current && current !== document.body) {
1201
+ offsetTop += current.offsetTop;
1202
+ current = current.offsetParent;
1203
+ }
1204
+
1205
+ if (!current) {
1206
+ return NaN;
1207
+ }
1208
+
1209
+ return offsetTop;
1210
+ }
1211
+
1212
+ function getOutlineScrollOffset() {
1213
+ var styles = window.getComputedStyle(root);
1214
+ var navHeight = parseFloat(styles.getPropertyValue('--vp-nav-height')) || 0;
1215
+ var layoutTopHeight = parseFloat(styles.getPropertyValue('--vp-layout-top-height')) || 0;
1216
+ return navHeight + layoutTopHeight;
1217
+ }
1218
+
1219
+ function activateOutlineHash(activeHash) {
1220
+ document.querySelectorAll('.outline-link').forEach(function (link) {
1221
+ var isActive = activeHash !== null && link.getAttribute('href') === activeHash;
1222
+ link.classList.toggle('active', isActive);
1223
+ });
1224
+
1225
+ if (!marker) {
1226
+ return;
1227
+ }
1228
+
1229
+ var activeAsideLink = document.querySelector('.VPDocAsideOutline .outline-link.active');
1230
+ if (activeAsideLink) {
1231
+ marker.style.top = String(activeAsideLink.offsetTop + 39) + 'px';
1232
+ marker.style.opacity = '1';
1233
+ } else {
1234
+ marker.style.top = '33px';
1235
+ marker.style.opacity = '0';
1236
+ }
1237
+ }
1238
+
1239
+ function syncActiveHeading() {
1240
+ if (!hasOutline) {
1241
+ return;
1242
+ }
1243
+
1244
+ var scrollY = window.scrollY || window.pageYOffset || 0;
1245
+ var innerHeight = window.innerHeight || 0;
1246
+ var offsetHeight = document.body ? document.body.offsetHeight : 0;
1247
+ var isBottom = Math.abs(scrollY + innerHeight - offsetHeight) < 1;
1248
+
1249
+ var resolvedHeadings = headings
1250
+ .map(function (heading) {
1251
+ return {
1252
+ hash: '#' + heading.id,
1253
+ top: getAbsoluteTop(heading)
1254
+ };
1255
+ })
1256
+ .filter(function (entry) {
1257
+ return !Number.isNaN(entry.top);
1258
+ })
1259
+ .sort(function (a, b) {
1260
+ return a.top - b.top;
1261
+ });
1262
+
1263
+ if (!resolvedHeadings.length) {
1264
+ activateOutlineHash(null);
1265
+ return;
1266
+ }
1267
+
1268
+ if (scrollY < 1) {
1269
+ activateOutlineHash(null);
1270
+ return;
1271
+ }
1272
+
1273
+ if (isBottom) {
1274
+ activateOutlineHash(resolvedHeadings[resolvedHeadings.length - 1].hash);
1275
+ return;
1276
+ }
1277
+
1278
+ var threshold = scrollY + getOutlineScrollOffset() + 4;
1279
+ var activeHash = null;
1280
+
1281
+ resolvedHeadings.forEach(function (entry) {
1282
+ if (entry.top > threshold) {
1283
+ return;
1284
+ }
1285
+ activeHash = entry.hash;
1286
+ });
1287
+
1288
+ activateOutlineHash(activeHash);
1289
+ }
1290
+
1291
+ syncActiveHeading();
1292
+ window.addEventListener('scroll', syncActiveHeading, { passive: true });
1293
+
1294
+ if (localOutlineContainer) {
1295
+ localOutlineContainer.querySelectorAll('a').forEach(function (link) {
1296
+ link.addEventListener('click', function () {
1297
+ closeLocalOutline();
1298
+ });
1299
+ });
1300
+ }
1301
+ })();