sourcey 2.1.0 → 3.0.1

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 (133) hide show
  1. package/README.md +128 -210
  2. package/dist/cli.js +18 -57
  3. package/dist/cli.js.map +1 -1
  4. package/dist/client/scroll-tracker.js +125 -40
  5. package/dist/client/search.js +27 -3
  6. package/dist/client/tabs.js +164 -24
  7. package/dist/components/App.d.ts +3 -2
  8. package/dist/components/App.d.ts.map +1 -1
  9. package/dist/components/App.js +3 -3
  10. package/dist/components/App.js.map +1 -1
  11. package/dist/components/layout/Head.d.ts.map +1 -1
  12. package/dist/components/layout/Head.js +30 -9
  13. package/dist/components/layout/Head.js.map +1 -1
  14. package/dist/components/layout/Header.d.ts +2 -7
  15. package/dist/components/layout/Header.d.ts.map +1 -1
  16. package/dist/components/layout/Header.js +12 -15
  17. package/dist/components/layout/Header.js.map +1 -1
  18. package/dist/components/layout/Page.d.ts.map +1 -1
  19. package/dist/components/layout/Page.js +54 -10
  20. package/dist/components/layout/Page.js.map +1 -1
  21. package/dist/components/layout/Sidebar.js +1 -1
  22. package/dist/components/layout/Sidebar.js.map +1 -1
  23. package/dist/components/layout/TableOfContents.d.ts.map +1 -1
  24. package/dist/components/layout/TableOfContents.js +1 -1
  25. package/dist/components/layout/TableOfContents.js.map +1 -1
  26. package/dist/components/openapi/CodeSamples.d.ts +4 -2
  27. package/dist/components/openapi/CodeSamples.d.ts.map +1 -1
  28. package/dist/components/openapi/CodeSamples.js +9 -5
  29. package/dist/components/openapi/CodeSamples.js.map +1 -1
  30. package/dist/components/openapi/Definition.js +1 -1
  31. package/dist/components/openapi/Definition.js.map +1 -1
  32. package/dist/components/openapi/EndpointBar.d.ts.map +1 -1
  33. package/dist/components/openapi/EndpointBar.js +3 -3
  34. package/dist/components/openapi/EndpointBar.js.map +1 -1
  35. package/dist/components/openapi/Introduction.d.ts.map +1 -1
  36. package/dist/components/openapi/Introduction.js +1 -1
  37. package/dist/components/openapi/Introduction.js.map +1 -1
  38. package/dist/components/openapi/Operation.d.ts.map +1 -1
  39. package/dist/components/openapi/Operation.js +5 -1
  40. package/dist/components/openapi/Operation.js.map +1 -1
  41. package/dist/components/openapi/Responses.d.ts +2 -1
  42. package/dist/components/openapi/Responses.d.ts.map +1 -1
  43. package/dist/components/openapi/Responses.js +17 -6
  44. package/dist/components/openapi/Responses.js.map +1 -1
  45. package/dist/components/openapi/Security.d.ts.map +1 -1
  46. package/dist/components/openapi/Security.js +3 -2
  47. package/dist/components/openapi/Security.js.map +1 -1
  48. package/dist/components/openapi/Tags.d.ts.map +1 -1
  49. package/dist/components/openapi/Tags.js +1 -1
  50. package/dist/components/openapi/Tags.js.map +1 -1
  51. package/dist/components/schema/ExampleView.d.ts +1 -1
  52. package/dist/components/schema/ExampleView.d.ts.map +1 -1
  53. package/dist/components/schema/ExampleView.js +3 -2
  54. package/dist/components/schema/ExampleView.js.map +1 -1
  55. package/dist/components/ui/CopyButton.d.ts +6 -0
  56. package/dist/components/ui/CopyButton.d.ts.map +1 -0
  57. package/dist/components/ui/CopyButton.js +10 -0
  58. package/dist/components/ui/CopyButton.js.map +1 -0
  59. package/dist/components/ui/Markdown.js +1 -1
  60. package/dist/components/ui/Markdown.js.map +1 -1
  61. package/dist/components/ui/SocialIcon.d.ts +5 -0
  62. package/dist/components/ui/SocialIcon.d.ts.map +1 -0
  63. package/dist/components/ui/SocialIcon.js +19 -0
  64. package/dist/components/ui/SocialIcon.js.map +1 -0
  65. package/dist/config.d.ts +133 -37
  66. package/dist/config.d.ts.map +1 -1
  67. package/dist/config.js +227 -73
  68. package/dist/config.js.map +1 -1
  69. package/dist/core/doxygen-loader.d.ts +9 -0
  70. package/dist/core/doxygen-loader.d.ts.map +1 -0
  71. package/dist/core/doxygen-loader.js +68 -0
  72. package/dist/core/doxygen-loader.js.map +1 -0
  73. package/dist/core/markdown-loader.d.ts +2 -5
  74. package/dist/core/markdown-loader.d.ts.map +1 -1
  75. package/dist/core/markdown-loader.js +218 -27
  76. package/dist/core/markdown-loader.js.map +1 -1
  77. package/dist/core/navigation.d.ts +2 -2
  78. package/dist/core/navigation.d.ts.map +1 -1
  79. package/dist/core/navigation.js +9 -10
  80. package/dist/core/navigation.js.map +1 -1
  81. package/dist/core/search-indexer.d.ts +1 -1
  82. package/dist/core/search-indexer.d.ts.map +1 -1
  83. package/dist/core/search-indexer.js +6 -5
  84. package/dist/core/search-indexer.js.map +1 -1
  85. package/dist/dev-server.d.ts +0 -12
  86. package/dist/dev-server.d.ts.map +1 -1
  87. package/dist/dev-server.js +101 -79
  88. package/dist/dev-server.js.map +1 -1
  89. package/dist/index.d.ts +2 -30
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/index.js +82 -70
  92. package/dist/index.js.map +1 -1
  93. package/dist/renderer/context.d.ts +29 -2
  94. package/dist/renderer/context.d.ts.map +1 -1
  95. package/dist/renderer/context.js +1 -1
  96. package/dist/renderer/context.js.map +1 -1
  97. package/dist/renderer/html-builder.d.ts +3 -16
  98. package/dist/renderer/html-builder.d.ts.map +1 -1
  99. package/dist/renderer/html-builder.js +6 -20
  100. package/dist/renderer/html-builder.js.map +1 -1
  101. package/dist/renderer/static-renderer.d.ts +2 -2
  102. package/dist/renderer/static-renderer.d.ts.map +1 -1
  103. package/dist/renderer/static-renderer.js +2 -2
  104. package/dist/renderer/static-renderer.js.map +1 -1
  105. package/dist/themes/default/main.css +13 -1
  106. package/dist/themes/default/sourcey.css +629 -41
  107. package/dist/utils/code-samples.d.ts +8 -3
  108. package/dist/utils/code-samples.d.ts.map +1 -1
  109. package/dist/utils/code-samples.js +188 -51
  110. package/dist/utils/code-samples.js.map +1 -1
  111. package/dist/utils/copy-svg.d.ts +9 -0
  112. package/dist/utils/copy-svg.d.ts.map +1 -0
  113. package/dist/utils/copy-svg.js +9 -0
  114. package/dist/utils/copy-svg.js.map +1 -0
  115. package/dist/utils/highlighter.d.ts.map +1 -1
  116. package/dist/utils/highlighter.js +18 -7
  117. package/dist/utils/highlighter.js.map +1 -1
  118. package/dist/utils/icons.d.ts +14 -0
  119. package/dist/utils/icons.d.ts.map +1 -0
  120. package/dist/utils/icons.js +59 -0
  121. package/dist/utils/icons.js.map +1 -0
  122. package/dist/utils/lang-icons.d.ts +17 -0
  123. package/dist/utils/lang-icons.d.ts.map +1 -0
  124. package/dist/utils/lang-icons.js +87 -0
  125. package/dist/utils/lang-icons.js.map +1 -0
  126. package/dist/utils/markdown.d.ts +17 -1
  127. package/dist/utils/markdown.d.ts.map +1 -1
  128. package/dist/utils/markdown.js +59 -2
  129. package/dist/utils/markdown.js.map +1 -1
  130. package/dist/vite-plugin.d.ts.map +1 -1
  131. package/dist/vite-plugin.js +4 -7
  132. package/dist/vite-plugin.js.map +1 -1
  133. package/package.json +5 -4
@@ -6,9 +6,23 @@
6
6
  (function () {
7
7
  var navLinks = document.querySelectorAll('#nav .nav-link');
8
8
  var targets = document.querySelectorAll('[data-traverse-target]');
9
- if (!targets.length || !navLinks.length) return;
9
+
10
+ // For prose pages, also track heading elements that TOC links point to
11
+ var tocHeadingEls = [];
12
+ document.querySelectorAll('#toc .toc-item').forEach(function (link) {
13
+ var href = link.getAttribute('href');
14
+ if (href && href.indexOf('#') !== -1) {
15
+ var el = document.getElementById(href.split('#')[1]);
16
+ if (el) tocHeadingEls.push(el);
17
+ }
18
+ });
19
+
20
+ if (!targets.length && !tocHeadingEls.length) return;
21
+ if (!navLinks.length && !tocHeadingEls.length) return;
10
22
 
11
23
  var currentId = null;
24
+ var clickedId = null; // When set, overrides scroll-based activation
25
+ var clickTimer = null;
12
26
 
13
27
  // Map traverse-target id → nav link element (by matching href fragment)
14
28
  var linkMap = {};
@@ -19,70 +33,141 @@
19
33
  }
20
34
  });
21
35
 
22
- // If no fragment-based links found, bail (e.g. markdown pages)
23
- if (!Object.keys(linkMap).length) return;
36
+ // If no fragment-based nav links AND no TOC headings, nothing to track
37
+ if (!Object.keys(linkMap).length && !tocHeadingEls.length) return;
38
+
39
+ // TOC links (right sidebar) — share the same scroll tracking
40
+ var tocLinks = document.querySelectorAll('#toc .toc-item');
41
+ var tocMap = {};
42
+ tocLinks.forEach(function (link) {
43
+ var href = link.getAttribute('href');
44
+ if (href && href.indexOf('#') !== -1) {
45
+ tocMap[href.split('#')[1]] = link;
46
+ }
47
+ });
48
+
49
+ // Only manage active state on fragment-linked nav items and TOC items.
50
+ // Doc page nav links keep their SSR-set active class untouched.
51
+ var fragmentNavLinks = Object.values(linkMap);
24
52
 
25
- function activate(id) {
26
- if (id === currentId) return;
53
+ function activate(id, force) {
54
+ if (id === currentId && !force) return;
27
55
  currentId = id;
28
56
 
29
- navLinks.forEach(function (link) {
57
+ fragmentNavLinks.forEach(function (link) {
58
+ link.classList.remove('active');
59
+ });
60
+ tocLinks.forEach(function (link) {
30
61
  link.classList.remove('active');
31
62
  });
32
63
 
33
64
  var active = linkMap[id];
34
65
  if (active) {
35
66
  active.classList.add('active');
36
- // Scroll the sidebar so the active link stays visible
37
67
  active.scrollIntoView({ block: 'nearest', behavior: 'auto' });
38
68
  }
69
+
70
+ var tocActive = tocMap[id];
71
+ if (tocActive) {
72
+ tocActive.classList.add('active');
73
+ }
39
74
  }
40
75
 
41
- // Track which sections are visible; pick the topmost one
42
- var visibleSections = new Map();
76
+ // Handle anchor clicks: activate highlight, scroll with header offset, lock scroll tracker.
77
+ function handleAnchorClick(e, selector) {
78
+ var link = e.target.closest(selector);
79
+ if (!link) return;
80
+ var href = link.getAttribute('href');
81
+ if (!href || href.indexOf('#') === -1) return;
82
+ var id = href.split('#')[1];
83
+ if (!id) return;
43
84
 
44
- var observer = new IntersectionObserver(function (entries) {
45
- entries.forEach(function (entry) {
46
- var id = entry.target.getAttribute('data-traverse-target');
47
- if (entry.isIntersecting) {
48
- visibleSections.set(id, entry.target);
49
- } else {
50
- visibleSections.delete(id);
51
- }
52
- });
85
+ e.preventDefault();
86
+ clickedId = id;
87
+ activate(id, true);
53
88
 
54
- // Pick the topmost visible section (smallest boundingClientRect.top)
89
+ var el = document.getElementById(id);
90
+ if (el) {
91
+ var header = document.getElementById('header');
92
+ var offset = (header ? header.offsetHeight : 112) + 16;
93
+ window.scrollTo({ top: el.getBoundingClientRect().top + window.scrollY - offset, behavior: 'smooth' });
94
+ history.replaceState(null, '', '#' + id);
95
+ }
96
+
97
+ clearTimeout(clickTimer);
98
+ clickTimer = setTimeout(function () { clickedId = null; }, 800);
99
+ }
100
+
101
+ var tocEl = document.getElementById('toc');
102
+ if (tocEl) tocEl.addEventListener('click', function (e) { handleAnchorClick(e, '.toc-item'); });
103
+
104
+ var navEl = document.getElementById('nav');
105
+ if (navEl) navEl.addEventListener('click', function (e) { handleAnchorClick(e, '.nav-link'); });
106
+
107
+ // Use scroll event for reliable activation at all positions.
108
+ function onScroll() {
109
+ // If a nav link was just clicked, don't override it until scroll settles
110
+ if (clickedId) return;
111
+
112
+ // Measure the actual header element to handle any template/theme height
113
+ var header = document.getElementById('header');
114
+ var threshold = (header ? header.offsetHeight : 112) + 20;
55
115
  var best = null;
56
- var bestTop = Infinity;
57
- visibleSections.forEach(function (el, id) {
58
- var top = el.getBoundingClientRect().top;
59
- if (top < bestTop) { bestTop = top; best = id; }
60
- });
61
116
 
62
- // Fallback: if nothing visible, find the last section above viewport
63
- if (!best) {
64
- for (var i = targets.length - 1; i >= 0; i--) {
65
- if (targets[i].getBoundingClientRect().top < 10) {
66
- best = targets[i].getAttribute('data-traverse-target');
67
- break;
68
- }
117
+ // Check API traverse targets
118
+ for (var i = 0; i < targets.length; i++) {
119
+ var top = targets[i].getBoundingClientRect().top;
120
+ if (top <= threshold) {
121
+ best = targets[i].getAttribute('data-traverse-target');
122
+ } else {
123
+ break;
124
+ }
125
+ }
126
+
127
+ // Check TOC heading elements (prose pages)
128
+ for (var j = 0; j < tocHeadingEls.length; j++) {
129
+ var hTop = tocHeadingEls[j].getBoundingClientRect().top;
130
+ if (hTop <= threshold) {
131
+ best = tocHeadingEls[j].id;
132
+ } else {
133
+ break;
69
134
  }
70
135
  }
71
136
 
137
+ // At top of page, default to first section
138
+ var allTargets = targets.length ? targets : tocHeadingEls;
139
+ if (!best && allTargets.length) {
140
+ best = targets.length
141
+ ? allTargets[0].getAttribute('data-traverse-target')
142
+ : allTargets[0].id;
143
+ }
144
+
145
+ // At bottom of page, force last section active
146
+ if (window.innerHeight + window.scrollY >= document.body.scrollHeight - 10) {
147
+ var last = allTargets[allTargets.length - 1];
148
+ best = targets.length ? last.getAttribute('data-traverse-target') : last.id;
149
+ }
150
+
72
151
  if (best) activate(best);
73
- }, {
74
- // Trigger when section header enters top 20% of viewport
75
- rootMargin: '0px 0px -80% 0px',
76
- threshold: 0
77
- });
152
+ }
78
153
 
79
- targets.forEach(function (el) { observer.observe(el); });
154
+ // Throttle scroll handler
155
+ var ticking = false;
156
+ window.addEventListener('scroll', function () {
157
+ if (!ticking) {
158
+ ticking = true;
159
+ requestAnimationFrame(function () {
160
+ onScroll();
161
+ ticking = false;
162
+ });
163
+ }
164
+ }, { passive: true });
80
165
 
81
- // Activate on initial load based on URL hash or first section
166
+ // Activate on initial load based on URL hash or scroll position
82
167
  var hash = window.location.hash.slice(1);
83
168
  if (hash && linkMap[hash]) {
84
169
  activate(hash);
85
- } else if (targets.length) {
86
- activate(targets[0].getAttribute('data-traverse-target'));
170
+ } else {
171
+ onScroll();
87
172
  }
88
173
  })();
@@ -68,12 +68,29 @@
68
68
  });
69
69
  }
70
70
 
71
+ // Sort by category so groups stay together
72
+ var categoryOrder = { Pages: 0, Sections: 1, Endpoints: 2, Models: 3 };
73
+ filtered.sort(function (a, b) {
74
+ return (categoryOrder[a.category] || 9) - (categoryOrder[b.category] || 9);
75
+ });
76
+
71
77
  activeIndex = filtered.length ? 0 : -1;
72
78
  render();
73
79
  }
74
80
 
75
81
  function render() {
76
- results.innerHTML = filtered.map(function (e, i) {
82
+ var html = '';
83
+ var lastCategory = '';
84
+
85
+ for (var i = 0; i < filtered.length; i++) {
86
+ var e = filtered[i];
87
+ var cat = e.category || 'Results';
88
+
89
+ if (cat !== lastCategory) {
90
+ html += '<div class="search-category">' + escapeHtml(cat) + '</div>';
91
+ lastCategory = cat;
92
+ }
93
+
77
94
  var cls = 'search-result' + (i === activeIndex ? ' active' : '');
78
95
  var label = e.method
79
96
  ? '<span class="search-result-method method-' + e.method.toLowerCase() + '">' + e.method + '</span> ' +
@@ -81,10 +98,17 @@
81
98
  : '<span class="search-result-path">' + escapeHtml(e.summary) + '</span>';
82
99
  var tagLine = e.tag ? '<span class="search-result-tag">' + escapeHtml(e.tag) + '</span>' : '';
83
100
  var summaryLine = e.method && e.summary ? '<span class="search-result-summary">' + escapeHtml(e.summary) + '</span>' : '';
84
- return '<a href="' + e.url + '" class="' + cls + '" data-index="' + i + '">' +
101
+
102
+ html += '<a href="' + e.url + '" class="' + cls + '" data-index="' + i + '">' +
85
103
  '<div class="search-result-main">' + label + summaryLine + '</div>' +
86
104
  tagLine + '</a>';
87
- }).join('');
105
+ }
106
+
107
+ results.innerHTML = html;
108
+
109
+ // Scroll active result into view
110
+ var activeEl = results.querySelector('.search-result.active');
111
+ if (activeEl) activeEl.scrollIntoView({ block: 'nearest' });
88
112
  }
89
113
 
90
114
  function escapeHtml(s) {
@@ -1,32 +1,66 @@
1
- // Code sample tabs switches active tab and syncs language across groups.
1
+ // Code sample language dropdown + response code tabs + copy button.
2
2
  //
3
- // Toggles .active on .code-samples-tab and .code-samples-panel elements.
4
- // All visual styling (color, underline indicator) is in sourcey.css;
5
- // this file only manages the .active class and aria-selected attribute.
3
+ // Handles three interaction patterns:
4
+ // 1. Language dropdown toggles .code-lang-menu, switches .code-lang-panel
5
+ // 2. Response tabs switches .response-tab active state + .response-panel
6
+ // 3. Copy button — copies code from the active panel to clipboard
6
7
  (function () {
7
8
  var selectedLang = null;
8
9
 
10
+ // ── Language Dropdown ──────────────────────────────────────────────
11
+
12
+ // Toggle dropdown open/close
9
13
  document.addEventListener('click', function (e) {
10
- var tab = e.target.closest('.code-samples-tab');
11
- if (!tab) return;
14
+ var trigger = e.target.closest('.code-lang-trigger');
12
15
 
13
- var container = tab.closest('.code-samples');
14
- var index = tab.getAttribute('data-tab-index');
15
- var lang = tab.textContent.trim();
16
+ // Close all open dropdowns first
17
+ document.querySelectorAll('.code-lang-menu').forEach(function (menu) {
18
+ if (!trigger || !menu.parentElement.contains(trigger)) {
19
+ menu.classList.add('hidden');
20
+ var btn = menu.parentElement.querySelector('.code-lang-trigger');
21
+ if (btn) btn.setAttribute('aria-expanded', 'false');
22
+ }
23
+ });
16
24
 
17
- // Preserve scroll position so panel height changes don't shift the page
18
- var scrollY = window.scrollY;
25
+ if (!trigger) return;
26
+ e.stopPropagation();
27
+
28
+ var menu = trigger.nextElementSibling;
29
+ if (!menu) return;
19
30
 
20
- activateTab(container, index);
31
+ var isOpen = !menu.classList.contains('hidden');
32
+ menu.classList.toggle('hidden', isOpen);
33
+ trigger.setAttribute('aria-expanded', isOpen ? 'false' : 'true');
34
+ });
21
35
 
22
- // Sync: activate same language in all other code-sample groups on the page
36
+ // Select a language from the dropdown
37
+ document.addEventListener('click', function (e) {
38
+ var option = e.target.closest('.code-lang-option');
39
+ if (!option) return;
40
+
41
+ var container = option.closest('.code-group');
42
+ var index = option.getAttribute('data-lang-index');
43
+ var lang = option.textContent.trim();
44
+
45
+ // Close the menu
46
+ var menu = option.closest('.code-lang-menu');
47
+ if (menu) {
48
+ menu.classList.add('hidden');
49
+ var trigger = menu.parentElement.querySelector('.code-lang-trigger');
50
+ if (trigger) trigger.setAttribute('aria-expanded', 'false');
51
+ }
52
+
53
+ var scrollY = window.scrollY;
54
+ activateLang(container, index);
55
+
56
+ // Sync language across all code-sample groups
23
57
  if (lang !== selectedLang) {
24
58
  selectedLang = lang;
25
- document.querySelectorAll('.code-samples').forEach(function (group) {
26
- if (group === container) return;
27
- group.querySelectorAll('.code-samples-tab').forEach(function (t) {
28
- if (t.textContent.trim() === lang) {
29
- activateTab(group, t.getAttribute('data-tab-index'));
59
+ document.querySelectorAll('.code-group').forEach(function (group) {
60
+ if (group === container || !group.querySelector('.code-lang-dropdown')) return;
61
+ group.querySelectorAll('.code-lang-option').forEach(function (opt) {
62
+ if (opt.textContent.trim() === lang) {
63
+ activateLang(group, opt.getAttribute('data-lang-index'));
30
64
  }
31
65
  });
32
66
  });
@@ -35,17 +69,123 @@
35
69
  window.scrollTo(0, scrollY);
36
70
  });
37
71
 
38
- function activateTab(container, index) {
72
+ function activateLang(container, index) {
73
+ // Update dropdown label
74
+ var options = container.querySelectorAll('.code-lang-option');
75
+ var label = container.querySelector('.code-lang-label');
76
+ options.forEach(function (opt) {
77
+ var isActive = opt.getAttribute('data-lang-index') === index;
78
+ opt.setAttribute('aria-selected', isActive ? 'true' : 'false');
79
+ opt.className = opt.className.replace(/text-\[rgb\([^\)]+\)\]/g, '');
80
+ if (isActive) {
81
+ opt.classList.add('text-[rgb(var(--color-primary))]');
82
+ if (label) label.textContent = opt.textContent.trim();
83
+ // Update trigger icon to match selected language
84
+ var triggerIcon = container.querySelector('.code-lang-trigger .code-lang-icon');
85
+ var optIcon = opt.querySelector('.lang-icon');
86
+ if (triggerIcon && optIcon) {
87
+ triggerIcon.innerHTML = optIcon.outerHTML;
88
+ }
89
+ } else {
90
+ opt.classList.add('text-[rgb(var(--color-stone-600))]');
91
+ }
92
+ });
93
+
94
+ // Update panels
95
+ container.querySelectorAll('.code-lang-panel').forEach(function (p) {
96
+ p.classList.toggle('active', p.getAttribute('data-lang-panel') === index);
97
+ });
98
+ }
99
+
100
+ // ── Response Tabs ──────────────────────────────────────────────────
101
+
102
+ document.addEventListener('click', function (e) {
103
+ var tab = e.target.closest('.response-tab');
104
+ if (!tab) return;
105
+
106
+ var container = tab.closest('.response-tabs');
107
+ var index = tab.getAttribute('data-response-index');
108
+ var scrollY = window.scrollY;
109
+
39
110
  // Update tabs
40
- container.querySelectorAll('.code-samples-tab').forEach(function (t) {
41
- var isActive = t.getAttribute('data-tab-index') === index;
111
+ container.querySelectorAll('.response-tab').forEach(function (t) {
112
+ var isActive = t.getAttribute('data-response-index') === index;
42
113
  t.classList.toggle('active', isActive);
43
114
  t.setAttribute('aria-selected', isActive ? 'true' : 'false');
44
115
  });
45
116
 
46
117
  // Update panels
47
- container.querySelectorAll('.code-samples-panel').forEach(function (p) {
48
- p.classList.toggle('active', p.getAttribute('data-panel-index') === index);
118
+ container.querySelectorAll('.response-panel').forEach(function (p) {
119
+ p.classList.toggle('active', p.getAttribute('data-response-panel') === index);
49
120
  });
50
- }
121
+
122
+ window.scrollTo(0, scrollY);
123
+ });
124
+
125
+ // ── Copy Button ────────────────────────────────────────────────────
126
+
127
+ document.addEventListener('click', function (e) {
128
+ var btn = e.target.closest('.copy-btn');
129
+ if (!btn) return;
130
+
131
+ var container = btn.closest('.code-group') || btn.closest('.code-block-wrapper');
132
+ if (!container) return;
133
+
134
+ // Find the active panel's code, or the nearest code block
135
+ var activePanel = container.querySelector('.code-lang-panel.active, .response-panel.active');
136
+ var codeEl = activePanel
137
+ ? activePanel.querySelector('.code-block, .font-mono')
138
+ : container.querySelector('.code-block, .font-mono');
139
+
140
+ if (!codeEl) return;
141
+
142
+ var text = codeEl.textContent || '';
143
+ navigator.clipboard.writeText(text).then(function () {
144
+ btn.classList.add('copied');
145
+ var tooltip = btn.nextElementSibling;
146
+ if (tooltip && tooltip.classList.contains('copy-tooltip')) {
147
+ tooltip.textContent = 'Copied!';
148
+ }
149
+ setTimeout(function () {
150
+ btn.classList.remove('copied');
151
+ if (tooltip && tooltip.classList.contains('copy-tooltip')) {
152
+ tooltip.textContent = 'Copy';
153
+ }
154
+ }, 2000);
155
+ });
156
+ });
157
+
158
+ // Close dropdowns on Escape
159
+ document.addEventListener('keydown', function (e) {
160
+ if (e.key === 'Escape') {
161
+ document.querySelectorAll('.code-lang-menu').forEach(function (menu) {
162
+ menu.classList.add('hidden');
163
+ var btn = menu.parentElement.querySelector('.code-lang-trigger');
164
+ if (btn) btn.setAttribute('aria-expanded', 'false');
165
+ });
166
+ }
167
+ });
168
+
169
+ // ── Directive Tabs (:::tabs and :::code-group) ────────────────────
170
+
171
+ document.addEventListener('click', function (e) {
172
+ var tab = e.target.closest('.directive-tab');
173
+ if (!tab) return;
174
+
175
+ var group = tab.getAttribute('data-tab-group');
176
+ var index = tab.getAttribute('data-tab-index');
177
+ var scrollY = window.scrollY;
178
+
179
+ // Update tab buttons
180
+ document.querySelectorAll('.directive-tab[data-tab-group="' + group + '"]').forEach(function (t) {
181
+ t.classList.toggle('active', t.getAttribute('data-tab-index') === index);
182
+ });
183
+
184
+ // Update panels
185
+ document.querySelectorAll('.directive-tab-panel[data-tab-group="' + group + '"]').forEach(function (p) {
186
+ p.classList.toggle('active', p.getAttribute('data-tab-index') === index);
187
+ });
188
+
189
+ window.scrollTo(0, scrollY);
190
+ });
51
191
  })();
@@ -1,15 +1,16 @@
1
1
  import type { NormalizedSpec } from "../core/types.js";
2
2
  import type { SiteNavigation } from "../core/navigation.js";
3
- import type { RenderOptions, CurrentPage } from "../renderer/context.js";
3
+ import type { RenderOptions, CurrentPage, SiteConfig } from "../renderer/context.js";
4
4
  export interface AppProps {
5
5
  spec: NormalizedSpec;
6
6
  options: RenderOptions;
7
7
  navigation: SiteNavigation;
8
8
  currentPage: CurrentPage;
9
+ site: SiteConfig;
9
10
  }
10
11
  /**
11
12
  * Root component. Renders a complete HTML document with modern layout.
12
13
  * When embeddable, renders just the page content without html/body wrapper.
13
14
  */
14
- export declare function App({ spec, options, navigation, currentPage }: AppProps): import("preact").JSX.Element;
15
+ export declare function App({ spec, options, navigation, currentPage, site }: AppProps): import("preact").JSX.Element;
15
16
  //# sourceMappingURL=App.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/components/App.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAO5D,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAIzE,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,aAAa,CAAC;IACvB,UAAU,EAAE,cAAc,CAAC;IAC3B,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAgB,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,EAAE,QAAQ,gCAwBvE"}
1
+ {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/components/App.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAQ5D,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAIrF,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,aAAa,CAAC;IACvB,UAAU,EAAE,cAAc,CAAC;IAC3B,WAAW,EAAE,WAAW,CAAC;IACzB,IAAI,EAAE,UAAU,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,QAAQ,gCA0B7E"}
@@ -1,13 +1,13 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
2
- import { SpecContext, OptionsContext, NavigationContext, PageContext, } from "../renderer/context.js";
2
+ import { SpecContext, OptionsContext, NavigationContext, PageContext, SiteContext, } from "../renderer/context.js";
3
3
  import { Head } from "./layout/Head.js";
4
4
  import { Page } from "./layout/Page.js";
5
5
  /**
6
6
  * Root component. Renders a complete HTML document with modern layout.
7
7
  * When embeddable, renders just the page content without html/body wrapper.
8
8
  */
9
- export function App({ spec, options, navigation, currentPage }) {
9
+ export function App({ spec, options, navigation, currentPage, site }) {
10
10
  const content = options.embeddable ? (_jsx(Page, {})) : (_jsxs("html", { lang: "en", children: [_jsx(Head, {}), _jsxs("body", { id: "sourcey", children: [_jsx(Page, {}), _jsx("script", { src: `${options.assetBase}sourcey.js`, defer: true })] })] }));
11
- return (_jsx(SpecContext.Provider, { value: spec, children: _jsx(OptionsContext.Provider, { value: options, children: _jsx(NavigationContext.Provider, { value: navigation, children: _jsx(PageContext.Provider, { value: currentPage, children: content }) }) }) }));
11
+ return (_jsx(SiteContext.Provider, { value: site, children: _jsx(SpecContext.Provider, { value: spec, children: _jsx(OptionsContext.Provider, { value: options, children: _jsx(NavigationContext.Provider, { value: navigation, children: _jsx(PageContext.Provider, { value: currentPage, children: content }) }) }) }) }));
12
12
  }
13
13
  //# sourceMappingURL=App.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"App.js","sourceRoot":"","sources":["../../src/components/App.tsx"],"names":[],"mappings":";AAEA,OAAO,EACL,WAAW,EACX,cAAc,EACd,iBAAiB,EACjB,WAAW,GACZ,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AASxC;;;GAGG;AACH,MAAM,UAAU,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAY;IACtE,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CACnC,KAAC,IAAI,KAAG,CACT,CAAC,CAAC,CAAC,CACF,gBAAM,IAAI,EAAC,IAAI,aACb,KAAC,IAAI,KAAG,EACR,gBAAM,EAAE,EAAC,SAAS,aAChB,KAAC,IAAI,KAAG,EACR,iBAAQ,GAAG,EAAE,GAAG,OAAO,CAAC,SAAS,YAAY,EAAE,KAAK,SAAG,IAClD,IACF,CACR,CAAC;IAEF,OAAO,CACL,KAAC,WAAW,CAAC,QAAQ,IAAC,KAAK,EAAE,IAAI,YAC/B,KAAC,cAAc,CAAC,QAAQ,IAAC,KAAK,EAAE,OAAO,YACrC,KAAC,iBAAiB,CAAC,QAAQ,IAAC,KAAK,EAAE,UAAU,YAC3C,KAAC,WAAW,CAAC,QAAQ,IAAC,KAAK,EAAE,WAAW,YACrC,OAAO,GACa,GACI,GACL,GACL,CACxB,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"App.js","sourceRoot":"","sources":["../../src/components/App.tsx"],"names":[],"mappings":";AAEA,OAAO,EACL,WAAW,EACX,cAAc,EACd,iBAAiB,EACjB,WAAW,EACX,WAAW,GACZ,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAUxC;;;GAGG;AACH,MAAM,UAAU,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,IAAI,EAAY;IAC5E,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CACnC,KAAC,IAAI,KAAG,CACT,CAAC,CAAC,CAAC,CACF,gBAAM,IAAI,EAAC,IAAI,aACb,KAAC,IAAI,KAAG,EACR,gBAAM,EAAE,EAAC,SAAS,aAChB,KAAC,IAAI,KAAG,EACR,iBAAQ,GAAG,EAAE,GAAG,OAAO,CAAC,SAAS,YAAY,EAAE,KAAK,SAAG,IAClD,IACF,CACR,CAAC;IAEF,OAAO,CACL,KAAC,WAAW,CAAC,QAAQ,IAAC,KAAK,EAAE,IAAI,YAC/B,KAAC,WAAW,CAAC,QAAQ,IAAC,KAAK,EAAE,IAAI,YAC/B,KAAC,cAAc,CAAC,QAAQ,IAAC,KAAK,EAAE,OAAO,YACrC,KAAC,iBAAiB,CAAC,QAAQ,IAAC,KAAK,EAAE,UAAU,YAC3C,KAAC,WAAW,CAAC,QAAQ,IAAC,KAAK,EAAE,WAAW,YACrC,OAAO,GACa,GACI,GACL,GACL,GACF,CACxB,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Head.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Head.tsx"],"names":[],"mappings":"AAGA,wBAAgB,IAAI,iCA6CnB"}
1
+ {"version":3,"file":"Head.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Head.tsx"],"names":[],"mappings":"AAIA,wBAAgB,IAAI,iCAuEnB"}
@@ -1,29 +1,50 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "preact/jsx-runtime";
2
2
  import { useContext } from "preact/hooks";
3
- import { SpecContext, OptionsContext, PageContext } from "../../renderer/context.js";
3
+ import { SpecContext, OptionsContext, PageContext, SiteContext, NavigationContext } from "../../renderer/context.js";
4
+ import { langIconCSS } from "../../utils/lang-icons.js";
4
5
  export function Head() {
6
+ const site = useContext(SiteContext);
5
7
  const spec = useContext(SpecContext);
6
8
  const options = useContext(OptionsContext);
7
9
  const page = useContext(PageContext);
8
- // Page title: use markdown page title, or spec title
9
- const siteName = spec.info.title || "";
10
+ const siteName = site.name || spec.info.title || "";
10
11
  const pageTitle = page.kind === "markdown"
11
12
  ? (siteName ? `${page.markdown.title} — ${siteName}` : page.markdown.title)
12
13
  : `${siteName} — API Reference`;
13
14
  const pageDescription = page.kind === "markdown"
14
15
  ? page.markdown.description || pageTitle
15
16
  : spec.info.description ?? `${siteName} API Documentation`;
16
- // Blocking style to prevent flash: sets body bg from design tokens
17
- // before the main stylesheet loads. The tokens are defined here as
18
- // fallback values matching main.css so there's no hardcoded hex.
19
- const antiFlashCSS = `
17
+ const nav = useContext(NavigationContext);
18
+ const { colors, fonts, layout } = site.theme;
19
+ const headerHeight = nav.tabs.length > 1 ? "7rem" : "4rem";
20
+ // Extract font family names for Google Fonts loading
21
+ const systemFonts = new Set(["system-ui", "sans-serif", "serif", "monospace", "-apple-system", "BlinkMacSystemFont", "Segoe UI", "Consolas", "SF Mono", "Fira Code", "Cascadia Code"]);
22
+ function extractFontName(stack) {
23
+ const m = stack.match(/^'([^']+)'/);
24
+ return m && !systemFonts.has(m[1]) ? m[1] : null;
25
+ }
26
+ const googleFonts = [extractFontName(fonts.sans), extractFontName(fonts.mono)].filter(Boolean);
27
+ const googleFontsUrl = googleFonts.length
28
+ ? "https://fonts.googleapis.com/css2?" + googleFonts.map(f => `family=${encodeURIComponent(f)}:wght@300;400;500;600;700`).join("&") + "&display=swap"
29
+ : null;
30
+ const themeCSS = `
20
31
  :root {
32
+ --color-primary: ${colors.primary};
33
+ --color-primary-light: ${colors.light};
34
+ --color-primary-dark: ${colors.dark};
21
35
  --color-background-light: 255 255 255;
22
36
  --color-background-dark: 11 12 16;
37
+ --font-sans: ${fonts.sans};
38
+ --font-mono: ${fonts.mono};
39
+ --sidebar-width: ${layout.sidebar};
40
+ --toc-width: ${layout.toc};
41
+ --content-max-width: ${layout.content};
42
+ --header-height: ${headerHeight};
23
43
  }
44
+ html { scroll-padding-top: ${headerHeight}; }
24
45
  body { margin: 0; background: rgb(var(--color-background-light)); }
25
46
  .dark body { background: rgb(var(--color-background-dark)); }
26
47
  `;
27
- return (_jsxs("head", { children: [_jsx("meta", { charset: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { children: pageTitle }), _jsx("meta", { name: "description", content: pageDescription }), _jsx("meta", { name: "sourcey-search", content: `${options.assetBase}search-index.json` }), _jsx("style", { dangerouslySetInnerHTML: { __html: antiFlashCSS } }), _jsx("script", { dangerouslySetInnerHTML: { __html: `(function(){var t=localStorage.getItem('sourcey-theme');if(t==='dark')document.documentElement.classList.add('dark')})()` } }), _jsx("link", { rel: "preconnect", href: "https://fonts.googleapis.com" }), _jsx("link", { rel: "preconnect", href: "https://fonts.gstatic.com", crossOrigin: "anonymous" }), _jsx("link", { rel: "stylesheet", href: "https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" }), _jsx("link", { rel: "stylesheet", href: `${options.assetBase}sourcey.css` }), spec.info.favicon && _jsx("link", { rel: "icon", href: spec.info.favicon })] }));
48
+ return (_jsxs("head", { children: [_jsx("meta", { charset: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { children: pageTitle }), _jsx("meta", { name: "description", content: pageDescription }), _jsx("meta", { name: "sourcey-search", content: `${options.assetBase}search-index.json` }), _jsx("style", { dangerouslySetInnerHTML: { __html: themeCSS } }), _jsx("style", { dangerouslySetInnerHTML: { __html: langIconCSS() } }), site.customCSS && _jsx("style", { dangerouslySetInnerHTML: { __html: site.customCSS } }), _jsx("script", { dangerouslySetInnerHTML: { __html: `(function(){var t=localStorage.getItem('sourcey-theme');if(t==='dark')document.documentElement.classList.add('dark')})()` } }), googleFontsUrl && (_jsxs(_Fragment, { children: [_jsx("link", { rel: "preconnect", href: "https://fonts.googleapis.com" }), _jsx("link", { rel: "preconnect", href: "https://fonts.gstatic.com", crossOrigin: "anonymous" }), _jsx("link", { rel: "stylesheet", href: googleFontsUrl })] })), _jsx("link", { rel: "stylesheet", href: `${options.assetBase}sourcey.css` }), site.favicon && _jsx("link", { rel: "icon", href: site.favicon })] }));
28
49
  }
29
50
  //# sourceMappingURL=Head.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Head.js","sourceRoot":"","sources":["../../../src/components/layout/Head.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAErF,MAAM,UAAU,IAAI;IAClB,MAAM,IAAI,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IACrC,MAAM,OAAO,GAAG,UAAU,CAAC,cAAc,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IAErC,qDAAqD;IACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;IACvC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,KAAK,UAAU;QACxC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,QAAS,CAAC,KAAK,MAAM,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAS,CAAC,KAAK,CAAC;QAC7E,CAAC,CAAC,GAAG,QAAQ,kBAAkB,CAAC;IAElC,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,KAAK,UAAU;QAC9C,CAAC,CAAC,IAAI,CAAC,QAAS,CAAC,WAAW,IAAI,SAAS;QACzC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,GAAG,QAAQ,oBAAoB,CAAC;IAE7D,mEAAmE;IACnE,mEAAmE;IACnE,iEAAiE;IACjE,MAAM,YAAY,GAAG;;;;;;;GAOpB,CAAC;IAEF,OAAO,CACL,2BACE,eAAM,OAAO,EAAC,OAAO,GAAG,EACxB,eAAM,IAAI,EAAC,UAAU,EAAC,OAAO,EAAC,qCAAqC,GAAG,EACtE,0BAAQ,SAAS,GAAS,EAC1B,eAAM,IAAI,EAAC,aAAa,EAAC,OAAO,EAAE,eAAe,GAAI,EACrD,eAAM,IAAI,EAAC,gBAAgB,EAAC,OAAO,EAAE,GAAG,OAAO,CAAC,SAAS,mBAAmB,GAAI,EAEhF,gBAAO,uBAAuB,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,GAAI,EAE5D,iBAAQ,uBAAuB,EAAE,EAAE,MAAM,EAAE,0HAA0H,EAAE,GAAI,EAC3K,eAAM,GAAG,EAAC,YAAY,EAAC,IAAI,EAAC,8BAA8B,GAAG,EAC7D,eAAM,GAAG,EAAC,YAAY,EAAC,IAAI,EAAC,2BAA2B,EAAC,WAAW,EAAC,WAAW,GAAG,EAClF,eAAM,GAAG,EAAC,YAAY,EAAC,IAAI,EAAC,sFAAsF,GAAG,EACrH,eAAM,GAAG,EAAC,YAAY,EAAC,IAAI,EAAE,GAAG,OAAO,CAAC,SAAS,aAAa,GAAI,EACjE,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,eAAM,GAAG,EAAC,MAAM,EAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,GAAI,IAC7D,CACR,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"Head.js","sourceRoot":"","sources":["../../../src/components/layout/Head.tsx"],"names":[],"mappings":"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"}
@@ -1,13 +1,8 @@
1
1
  /**
2
- * Two-row site header two-row layout.
3
- * Row 1 (h-16): logo, search, theme toggle
2
+ * Two-row site header.
3
+ * Row 1 (h-16): logo, search, navbar links, theme toggle
4
4
  * Row 2 (h-12): navigation tabs
5
5
  * Total: 7rem (header-height)
6
6
  */
7
7
  export declare function Header(): import("preact").JSX.Element;
8
- /**
9
- * Mobile header is now integrated into the main Header component.
10
- * This is kept as a no-op for backward compatibility.
11
- */
12
- export declare function MobileHeader(): null;
13
8
  //# sourceMappingURL=Header.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Header.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Header.tsx"],"names":[],"mappings":"AAsCA;;;;;GAKG;AACH,wBAAgB,MAAM,iCAwHrB;AAED;;;GAGG;AACH,wBAAgB,YAAY,SAE3B"}
1
+ {"version":3,"file":"Header.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Header.tsx"],"names":[],"mappings":"AAuCA;;;;;GAKG;AACH,wBAAgB,MAAM,iCAiKrB"}