sourcey 3.4.0 → 3.4.3

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 (49) hide show
  1. package/dist/client/scroll-tracker.js +168 -156
  2. package/dist/client/search.js +186 -160
  3. package/dist/client/sidebar.js +56 -48
  4. package/dist/client/tabs.js +154 -146
  5. package/dist/components/layout/Head.d.ts.map +1 -1
  6. package/dist/components/layout/Head.js +4 -12
  7. package/dist/components/layout/Header.d.ts.map +1 -1
  8. package/dist/components/layout/Header.js +3 -3
  9. package/dist/components/layout/Page.d.ts.map +1 -1
  10. package/dist/components/layout/Page.js +9 -9
  11. package/dist/components/layout/Sidebar.d.ts.map +1 -1
  12. package/dist/components/layout/Sidebar.js +18 -14
  13. package/dist/components/layout/TableOfContents.d.ts.map +1 -1
  14. package/dist/components/layout/TableOfContents.js +2 -1
  15. package/dist/components/openapi/EndpointBar.js +5 -5
  16. package/dist/components/openapi/Introduction.js +1 -1
  17. package/dist/components/openapi/Responses.js +4 -4
  18. package/dist/components/openapi/Security.js +1 -1
  19. package/dist/components/ui/SectionLabel.js +1 -1
  20. package/dist/config.d.ts +8 -0
  21. package/dist/config.d.ts.map +1 -1
  22. package/dist/config.js +7 -3
  23. package/dist/core/doxygen-loader.d.ts +1 -0
  24. package/dist/core/doxygen-loader.d.ts.map +1 -1
  25. package/dist/core/doxygen-loader.js +12 -3
  26. package/dist/core/markdown-loader.d.ts.map +1 -1
  27. package/dist/core/markdown-loader.js +46 -2
  28. package/dist/core/search-indexer.d.ts +3 -1
  29. package/dist/core/search-indexer.d.ts.map +1 -1
  30. package/dist/core/search-indexer.js +7 -3
  31. package/dist/dev-server.js +2 -2
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +7 -2
  34. package/dist/init.js +1 -1
  35. package/dist/renderer/html-builder.d.ts +2 -0
  36. package/dist/renderer/html-builder.d.ts.map +1 -1
  37. package/dist/renderer/html-builder.js +6 -0
  38. package/dist/renderer/llms.d.ts +6 -0
  39. package/dist/renderer/llms.d.ts.map +1 -0
  40. package/dist/renderer/llms.js +247 -0
  41. package/dist/themes/default/main.css +6 -3
  42. package/dist/themes/default/sourcey.css +92 -58
  43. package/dist/utils/icons.d.ts +4 -0
  44. package/dist/utils/icons.d.ts.map +1 -1
  45. package/dist/utils/icons.js +6 -0
  46. package/dist/utils/markdown.d.ts +10 -0
  47. package/dist/utils/markdown.d.ts.map +1 -1
  48. package/dist/utils/markdown.js +82 -6
  49. package/package.json +1 -1
@@ -1,189 +1,215 @@
1
1
  // Search — client-side search dialog with keyboard navigation
2
2
  (function () {
3
- var dialog = document.getElementById('search-dialog');
4
- var input = document.getElementById('search-input');
5
- var results = document.getElementById('search-results');
6
- var openBtn = document.getElementById('search-open');
7
- if (!dialog || !input || !results) return;
8
-
9
- var entries = [];
10
- var activeIndex = -1;
11
- var filtered = [];
12
- var indexLoaded = false;
13
-
14
- // Always load from JSON search index
15
- var searchMeta = document.querySelector('meta[name="sourcey-search"]');
16
-
17
- function loadJsonIndex(callback) {
18
- if (indexLoaded) { callback(); return; }
19
- if (!searchMeta) { indexLoaded = true; callback(); return; }
20
- var url = searchMeta.getAttribute('content');
21
- fetch(url).then(function (r) { return r.json(); }).then(function (data) {
22
- entries = data.map(function (e) {
23
- return {
24
- url: e.url,
25
- method: e.method || '',
26
- path: e.path || '',
27
- summary: e.title || '',
28
- tag: e.tab || '',
29
- content: e.content || '',
30
- category: e.category || '',
31
- searchText: [e.method || '', e.path || '', e.title || '', e.content || '', e.tab || ''].join(' ').toLowerCase()
32
- };
3
+ function init() {
4
+ var dialog = document.getElementById('search-dialog');
5
+ var input = document.getElementById('search-input');
6
+ var results = document.getElementById('search-results');
7
+ var openBtn = document.getElementById('search-open');
8
+ if (!dialog || !input || !results) return;
9
+
10
+ var entries = [];
11
+ var activeIndex = -1;
12
+ var filtered = [];
13
+ var indexLoaded = false;
14
+
15
+ // Always load from JSON search index
16
+ var searchMeta = document.querySelector('meta[name="sourcey-search"]');
17
+
18
+ function loadJsonIndex(callback) {
19
+ if (indexLoaded) { callback(); return; }
20
+ if (!searchMeta) { indexLoaded = true; callback(); return; }
21
+ var url = searchMeta.getAttribute('content');
22
+ fetch(url).then(function (r) { return r.json(); }).then(function (data) {
23
+ entries = data.map(function (e) {
24
+ return {
25
+ url: e.url,
26
+ method: e.method || '',
27
+ path: e.path || '',
28
+ summary: e.title || '',
29
+ tag: e.tab || '',
30
+ content: e.content || '',
31
+ category: e.category || '',
32
+ featured: !!e.featured,
33
+ searchText: [e.method || '', e.path || '', e.title || '', e.content || '', e.tab || ''].join(' ').toLowerCase()
34
+ };
35
+ });
36
+ indexLoaded = true;
37
+ callback();
38
+ }).catch(function () {
39
+ indexLoaded = true;
40
+ callback();
33
41
  });
34
- indexLoaded = true;
35
- callback();
36
- }).catch(function () {
37
- indexLoaded = true;
38
- callback();
39
- });
40
- }
41
-
42
- function open() {
43
- dialog.classList.add('open');
44
- input.value = '';
45
- input.focus();
46
- if (!indexLoaded) {
47
- results.innerHTML = '<div class="search-loading">Loading…</div>';
48
- loadJsonIndex(function () { showResults(''); });
49
- } else {
50
- showResults('');
51
42
  }
52
- document.addEventListener('keydown', onDialogKey);
53
- }
54
-
55
- function close() {
56
- dialog.classList.remove('open');
57
- document.removeEventListener('keydown', onDialogKey);
58
- }
59
43
 
60
- function showResults(query) {
61
- var q = query.toLowerCase().trim();
62
- if (!q) {
63
- filtered = entries.slice(0, 20);
64
- } else {
65
- var terms = q.split(/\s+/);
66
- filtered = entries.filter(function (e) {
67
- return terms.every(function (t) { return e.searchText.indexOf(t) !== -1; });
68
- });
44
+ var dialogInner = dialog.querySelector('.search-dialog-inner');
45
+
46
+ function positionDialog() {
47
+ if (!openBtn || !dialogInner) return;
48
+ var rect = openBtn.getBoundingClientRect();
49
+ dialogInner.style.position = 'absolute';
50
+ dialogInner.style.top = (rect.top - 4) + 'px';
51
+ var extraWidth = Math.min(rect.width * 0.5, 200);
52
+ dialogInner.style.left = (rect.left - extraWidth / 2) + 'px';
53
+ dialogInner.style.width = (rect.width + extraWidth) + 'px';
54
+ dialogInner.style.maxWidth = 'none';
55
+ dialogInner.style.transform = 'none';
56
+ dialogInner.style.margin = '0';
69
57
  }
70
58
 
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
-
77
- activeIndex = filtered.length ? 0 : -1;
78
- render();
79
- }
80
-
81
- function render() {
82
- var html = '';
83
- var lastCategory = '';
59
+ function open() {
60
+ positionDialog();
61
+ dialog.classList.add('open');
62
+ input.value = '';
63
+ input.focus();
64
+ if (!indexLoaded) {
65
+ results.innerHTML = '<div class="search-loading">Loading…</div>';
66
+ loadJsonIndex(function () { showResults(''); });
67
+ } else {
68
+ showResults('');
69
+ }
70
+ document.addEventListener('keydown', onDialogKey);
71
+ }
84
72
 
85
- for (var i = 0; i < filtered.length; i++) {
86
- var e = filtered[i];
87
- var cat = e.category || 'Results';
73
+ function close() {
74
+ dialog.classList.remove('open');
75
+ document.removeEventListener('keydown', onDialogKey);
76
+ }
88
77
 
89
- if (cat !== lastCategory) {
90
- html += '<div class="search-category">' + escapeHtml(cat) + '</div>';
91
- lastCategory = cat;
78
+ function showResults(query) {
79
+ var q = query.toLowerCase().trim();
80
+ if (!q) {
81
+ // Show featured pages first, then endpoints
82
+ var featured = entries.filter(function (e) { return e.featured; });
83
+ var rest = entries.filter(function (e) { return !e.featured && e.category !== 'Sections'; });
84
+ filtered = featured.concat(rest).slice(0, 30);
85
+ } else {
86
+ var terms = q.split(/\s+/);
87
+ filtered = entries.filter(function (e) {
88
+ return terms.every(function (t) { return e.searchText.indexOf(t) !== -1; });
89
+ });
90
+ // Sort by category so groups stay together (only for search results)
91
+ var categoryOrder = { Pages: 0, Sections: 1, Endpoints: 2, Models: 3 };
92
+ filtered.sort(function (a, b) {
93
+ return (categoryOrder[a.category] || 9) - (categoryOrder[b.category] || 9);
94
+ });
92
95
  }
93
96
 
94
- var cls = 'search-result' + (i === activeIndex ? ' active' : '');
95
- var label = e.method
96
- ? '<span class="search-result-method method-' + e.method.toLowerCase() + '">' + e.method + '</span> ' +
97
- '<span class="search-result-path">' + escapeHtml(e.path) + '</span>'
98
- : '<span class="search-result-path">' + escapeHtml(e.summary) + '</span>';
99
- var tagLine = e.tag ? '<span class="search-result-tag">' + escapeHtml(e.tag) + '</span>' : '';
100
- var summaryLine = e.method && e.summary ? '<span class="search-result-summary">' + escapeHtml(e.summary) + '</span>' : '';
101
-
102
- html += '<a href="' + e.url + '" class="' + cls + '" data-index="' + i + '">' +
103
- '<div class="search-result-main">' + label + summaryLine + '</div>' +
104
- tagLine + '</a>';
97
+ activeIndex = filtered.length ? 0 : -1;
98
+ render();
105
99
  }
106
100
 
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' });
112
- }
101
+ function render() {
102
+ var html = '';
103
+ var lastCategory = '';
104
+
105
+ for (var i = 0; i < filtered.length; i++) {
106
+ var e = filtered[i];
107
+ var cat = e.category || 'Results';
108
+
109
+ if (cat !== lastCategory) {
110
+ html += '<div class="search-category">' + escapeHtml(cat) + '</div>';
111
+ lastCategory = cat;
112
+ }
113
+
114
+ var cls = 'search-result' + (i === activeIndex ? ' active' : '');
115
+ var label = e.method
116
+ ? '<span class="search-result-method method-' + e.method.toLowerCase() + '">' + e.method + '</span> ' +
117
+ '<span class="search-result-path">' + escapeHtml(e.path) + '</span>'
118
+ : '<span class="search-result-path">' + escapeHtml(e.summary) + '</span>';
119
+ var tagLine = e.tag ? '<span class="search-result-tag">' + escapeHtml(e.tag) + '</span>' : '';
120
+ var summaryLine = e.method && e.summary ? '<span class="search-result-summary">' + escapeHtml(e.summary) + '</span>' : '';
121
+
122
+ html += '<a href="' + e.url + '" class="' + cls + '" data-index="' + i + '">' +
123
+ '<div class="search-result-main">' + label + summaryLine + '</div>' +
124
+ tagLine + '</a>';
125
+ }
113
126
 
114
- function escapeHtml(s) {
115
- var el = document.createElement('span');
116
- el.textContent = s;
117
- return el.innerHTML;
118
- }
127
+ results.innerHTML = html;
119
128
 
120
- function navigate(index) {
121
- if (index < 0 || index >= filtered.length) return;
122
- var entry = filtered[index];
123
- close();
124
- window.location.href = entry.url;
125
- }
129
+ // Scroll active result into view
130
+ var activeEl = results.querySelector('.search-result.active');
131
+ if (activeEl) activeEl.scrollIntoView({ block: 'nearest' });
132
+ }
126
133
 
127
- function onDialogKey(e) {
128
- if (e.key === 'Escape') { close(); e.preventDefault(); return; }
129
- if (e.key === 'ArrowDown') {
130
- e.preventDefault();
131
- activeIndex = Math.min(activeIndex + 1, filtered.length - 1);
132
- render();
133
- return;
134
+ function escapeHtml(s) {
135
+ var el = document.createElement('span');
136
+ el.textContent = s;
137
+ return el.innerHTML;
134
138
  }
135
- if (e.key === 'ArrowUp') {
136
- e.preventDefault();
137
- activeIndex = Math.max(activeIndex - 1, 0);
138
- render();
139
- return;
139
+
140
+ function navigate(index) {
141
+ if (index < 0 || index >= filtered.length) return;
142
+ var entry = filtered[index];
143
+ close();
144
+ window.location.href = entry.url;
140
145
  }
141
- if (e.key === 'Enter') {
142
- e.preventDefault();
143
- if (activeIndex >= 0) navigate(activeIndex);
144
- return;
146
+
147
+ function onDialogKey(e) {
148
+ if (e.key === 'Escape') { close(); e.preventDefault(); return; }
149
+ if (e.key === 'ArrowDown') {
150
+ e.preventDefault();
151
+ activeIndex = Math.min(activeIndex + 1, filtered.length - 1);
152
+ render();
153
+ return;
154
+ }
155
+ if (e.key === 'ArrowUp') {
156
+ e.preventDefault();
157
+ activeIndex = Math.max(activeIndex - 1, 0);
158
+ render();
159
+ return;
160
+ }
161
+ if (e.key === 'Enter') {
162
+ e.preventDefault();
163
+ if (activeIndex >= 0) navigate(activeIndex);
164
+ return;
165
+ }
145
166
  }
146
- }
147
167
 
148
- input.addEventListener('input', function () {
149
- showResults(input.value);
150
- });
168
+ input.addEventListener('input', function () {
169
+ showResults(input.value);
170
+ });
151
171
 
152
- results.addEventListener('click', function (e) {
153
- var result = e.target.closest('.search-result');
154
- if (result) {
155
- e.preventDefault();
156
- navigate(parseInt(result.getAttribute('data-index'), 10));
157
- }
158
- });
172
+ results.addEventListener('click', function (e) {
173
+ var result = e.target.closest('.search-result');
174
+ if (result) {
175
+ e.preventDefault();
176
+ navigate(parseInt(result.getAttribute('data-index'), 10));
177
+ }
178
+ });
159
179
 
160
- // Open search
161
- if (openBtn) openBtn.addEventListener('click', open);
180
+ // Open search
181
+ if (openBtn) openBtn.addEventListener('click', open);
162
182
 
163
- // Also bind mobile search button
164
- var mobileBtn = document.getElementById('search-open-mobile');
165
- if (mobileBtn) mobileBtn.addEventListener('click', open);
183
+ // Also bind mobile search button
184
+ var mobileBtn = document.getElementById('search-open-mobile');
185
+ if (mobileBtn) mobileBtn.addEventListener('click', open);
166
186
 
167
- // Keyboard shortcut: Ctrl+K or /
168
- document.addEventListener('keydown', function (e) {
169
- if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
170
- e.preventDefault();
171
- open();
172
- }
173
- if (e.key === '/' && !isEditable(e.target)) {
174
- e.preventDefault();
175
- open();
176
- }
177
- });
187
+ // Keyboard shortcut: Ctrl+K or /
188
+ document.addEventListener('keydown', function (e) {
189
+ if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
190
+ e.preventDefault();
191
+ open();
192
+ }
193
+ if (e.key === '/' && !isEditable(e.target)) {
194
+ e.preventDefault();
195
+ open();
196
+ }
197
+ });
178
198
 
179
- // Close on backdrop click
180
- dialog.addEventListener('click', function (e) {
181
- if (e.target === dialog) close();
182
- });
199
+ // Close on backdrop click
200
+ dialog.addEventListener('click', function (e) {
201
+ if (e.target === dialog) close();
202
+ });
183
203
 
184
- function isEditable(el) {
185
- var tag = el.tagName;
186
- return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || el.isContentEditable;
204
+ function isEditable(el) {
205
+ var tag = el.tagName;
206
+ return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || el.isContentEditable;
207
+ }
187
208
  }
188
209
 
210
+ if ('requestIdleCallback' in window) {
211
+ window.requestIdleCallback(init, { timeout: 250 });
212
+ } else {
213
+ window.addEventListener('load', init, { once: true });
214
+ }
189
215
  })();
@@ -4,63 +4,71 @@
4
4
  // backdrop click, nav link click, Escape (native dialog behavior).
5
5
  // Dropdown toggles list visibility for tab selection.
6
6
  (function () {
7
- var dialog = document.getElementById('mobile-nav');
8
- var openBtns = document.querySelectorAll('[data-drawer-slide]');
9
- if (!dialog) return;
7
+ function init() {
8
+ var dialog = document.getElementById('mobile-nav');
9
+ var openBtns = document.querySelectorAll('[data-drawer-slide]');
10
+ if (!dialog) return;
10
11
 
11
- // Sync active state from desktop sidebar to drawer on open
12
- function syncActiveState() {
13
- var activeDesktop = document.querySelector('#nav .nav-link.active');
14
- if (!activeDesktop) return;
15
- var activeHref = activeDesktop.getAttribute('href');
16
- if (!activeHref) return;
12
+ // Sync active state from desktop sidebar to drawer on open
13
+ function syncActiveState() {
14
+ var activeDesktop = document.querySelector('#nav .nav-link.active');
15
+ if (!activeDesktop) return;
16
+ var activeHref = activeDesktop.getAttribute('href');
17
+ if (!activeHref) return;
17
18
 
18
- dialog.querySelectorAll('.nav-link').forEach(function (link) {
19
- link.classList.toggle('active', link.getAttribute('href') === activeHref);
19
+ dialog.querySelectorAll('.nav-link').forEach(function (link) {
20
+ link.classList.toggle('active', link.getAttribute('href') === activeHref);
21
+ });
22
+ }
23
+
24
+ openBtns.forEach(function (btn) {
25
+ btn.addEventListener('click', function () {
26
+ syncActiveState();
27
+ dialog.showModal();
28
+ });
20
29
  });
21
- }
22
30
 
23
- openBtns.forEach(function (btn) {
24
- btn.addEventListener('click', function () {
25
- syncActiveState();
26
- dialog.showModal();
31
+ // Close on backdrop click (click on dialog element itself, not its children)
32
+ dialog.addEventListener('click', function (e) {
33
+ if (e.target === dialog) dialog.close();
27
34
  });
28
- });
29
35
 
30
- // Close on backdrop click (click on dialog element itself, not its children)
31
- dialog.addEventListener('click', function (e) {
32
- if (e.target === dialog) dialog.close();
33
- });
36
+ // Close on nav link or close button click
37
+ dialog.addEventListener('click', function (e) {
38
+ if (e.target.closest('a') || e.target.closest('[data-close-drawer]')) dialog.close();
39
+ });
34
40
 
35
- // Close on nav link or close button click
36
- dialog.addEventListener('click', function (e) {
37
- if (e.target.closest('a') || e.target.closest('[data-close-drawer]')) dialog.close();
38
- });
41
+ // Dropdown: toggle list visibility
42
+ var toggle = document.getElementById('drawer-group-toggle');
43
+ var list = document.getElementById('drawer-group-list');
44
+ if (!toggle || !list) return;
39
45
 
40
- // Dropdown: toggle list visibility
41
- var toggle = document.getElementById('drawer-group-toggle');
42
- var list = document.getElementById('drawer-group-list');
43
- if (!toggle || !list) return;
46
+ function closeDropdown() {
47
+ list.style.display = 'none';
48
+ toggle.setAttribute('aria-expanded', 'false');
49
+ }
44
50
 
45
- function closeDropdown() {
46
- list.style.display = 'none';
47
- toggle.setAttribute('aria-expanded', 'false');
48
- }
51
+ toggle.addEventListener('click', function () {
52
+ var open = list.style.display !== 'none';
53
+ if (open) {
54
+ closeDropdown();
55
+ } else {
56
+ list.style.display = '';
57
+ toggle.setAttribute('aria-expanded', 'true');
58
+ }
59
+ });
49
60
 
50
- toggle.addEventListener('click', function () {
51
- var open = list.style.display !== 'none';
52
- if (open) {
53
- closeDropdown();
54
- } else {
55
- list.style.display = '';
56
- toggle.setAttribute('aria-expanded', 'true');
57
- }
58
- });
61
+ // Close dropdown when clicking outside it
62
+ dialog.addEventListener('click', function (e) {
63
+ if (list.style.display !== 'none' && !e.target.closest('.drawer-dropdown')) {
64
+ closeDropdown();
65
+ }
66
+ });
67
+ }
59
68
 
60
- // Close dropdown when clicking outside it
61
- dialog.addEventListener('click', function (e) {
62
- if (list.style.display !== 'none' && !e.target.closest('.drawer-dropdown')) {
63
- closeDropdown();
64
- }
65
- });
69
+ if ('requestIdleCallback' in window) {
70
+ window.requestIdleCallback(init, { timeout: 250 });
71
+ } else {
72
+ window.addEventListener('load', init, { once: true });
73
+ }
66
74
  })();