rdoc 6.17.0 → 8.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +193 -0
- data/LEGAL.rdoc +6 -0
- data/LICENSE.rdoc +4 -0
- data/README.md +132 -8
- data/RI.md +75 -75
- data/doc/markup_reference/markdown.md +659 -0
- data/doc/markup_reference/rdoc.rdoc +1169 -0
- data/exe/rdoc +2 -2
- data/lib/rdoc/code_object/alias.rb +70 -74
- data/lib/rdoc/code_object/any_method.rb +308 -293
- data/lib/rdoc/code_object/attr.rb +150 -142
- data/lib/rdoc/code_object/class_module.rb +802 -715
- data/lib/rdoc/code_object/constant.rb +181 -144
- data/lib/rdoc/code_object/context/section.rb +140 -130
- data/lib/rdoc/code_object/context.rb +925 -941
- data/lib/rdoc/code_object/extend.rb +7 -5
- data/lib/rdoc/code_object/include.rb +7 -5
- data/lib/rdoc/code_object/method_attr.rb +328 -315
- data/lib/rdoc/code_object/mixin.rb +97 -92
- data/lib/rdoc/code_object/normal_class.rb +77 -78
- data/lib/rdoc/code_object/normal_module.rb +61 -59
- data/lib/rdoc/code_object/require.rb +23 -39
- data/lib/rdoc/code_object/single_class.rb +21 -19
- data/lib/rdoc/code_object/top_level.rb +215 -202
- data/lib/rdoc/code_object.rb +305 -305
- data/lib/rdoc/comment.rb +274 -337
- data/lib/rdoc/cross_reference.rb +195 -206
- data/lib/rdoc/encoding.rb +105 -103
- data/lib/rdoc/erb_partial.rb +13 -11
- data/lib/rdoc/erbio.rb +29 -27
- data/lib/rdoc/generator/aliki.rb +196 -30
- data/lib/rdoc/generator/darkfish.rb +647 -629
- data/lib/rdoc/generator/json_index.rb +233 -229
- data/lib/rdoc/generator/markup.rb +165 -122
- data/lib/rdoc/generator/pot/message_extractor.rb +57 -51
- data/lib/rdoc/generator/pot/po.rb +52 -51
- data/lib/rdoc/generator/pot/po_entry.rb +138 -132
- data/lib/rdoc/generator/pot.rb +85 -81
- data/lib/rdoc/generator/ri.rb +23 -19
- data/lib/rdoc/generator/template/aliki/DESIGN.md +538 -0
- data/lib/rdoc/generator/template/aliki/_aside_toc.rhtml +1 -1
- data/lib/rdoc/generator/template/aliki/_footer.rhtml +2 -2
- data/lib/rdoc/generator/template/aliki/_head.rhtml +15 -10
- data/lib/rdoc/generator/template/aliki/_header.rhtml +29 -44
- data/lib/rdoc/generator/template/aliki/_sidebar_extends.rhtml +8 -6
- data/lib/rdoc/generator/template/aliki/_sidebar_includes.rhtml +8 -6
- data/lib/rdoc/generator/template/aliki/_sidebar_installed.rhtml +1 -1
- data/lib/rdoc/generator/template/aliki/_sidebar_pages.rhtml +3 -3
- data/lib/rdoc/generator/template/aliki/_sidebar_search.rhtml +3 -3
- data/lib/rdoc/generator/template/aliki/_sidebar_sections.rhtml +1 -1
- data/lib/rdoc/generator/template/aliki/_sidebar_toggle.rhtml +1 -1
- data/lib/rdoc/generator/template/aliki/class.rhtml +71 -61
- data/lib/rdoc/generator/template/aliki/css/rdoc.css +796 -323
- data/lib/rdoc/generator/template/aliki/index.rhtml +1 -1
- data/lib/rdoc/generator/template/aliki/js/aliki.js +119 -113
- data/lib/rdoc/generator/template/aliki/js/bash_highlighter.js +167 -0
- data/lib/rdoc/generator/template/aliki/js/c_highlighter.js +1 -1
- data/lib/rdoc/generator/template/aliki/js/{search.js → search_controller.js} +16 -7
- data/lib/rdoc/generator/template/aliki/js/search_navigation.js +105 -0
- data/lib/rdoc/generator/template/aliki/js/search_ranker.js +239 -0
- data/lib/rdoc/generator/template/aliki/page.rhtml +1 -1
- data/lib/rdoc/generator/template/aliki/servlet_not_found.rhtml +1 -1
- data/lib/rdoc/generator/template/aliki/servlet_root.rhtml +2 -2
- data/lib/rdoc/generator/template/darkfish/_footer.rhtml +1 -1
- data/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml +8 -6
- data/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml +8 -6
- data/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml +1 -1
- data/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml +2 -2
- data/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml +1 -1
- data/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml +5 -5
- data/lib/rdoc/generator/template/darkfish/class.rhtml +29 -32
- data/lib/rdoc/generator/template/darkfish/css/rdoc.css +19 -1
- data/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml +3 -3
- data/lib/rdoc/generator.rb +48 -46
- data/lib/rdoc/i18n/locale.rb +99 -95
- data/lib/rdoc/i18n/text.rb +109 -105
- data/lib/rdoc/i18n.rb +7 -5
- data/lib/rdoc/markdown/byte_runtime.rb +80 -0
- data/lib/rdoc/markdown.kpeg +52 -33
- data/lib/rdoc/markdown.rb +365 -177
- data/lib/rdoc/markup/blank_line.rb +25 -23
- data/lib/rdoc/markup/block_quote.rb +12 -8
- data/lib/rdoc/markup/document.rb +127 -123
- data/lib/rdoc/markup/element.rb +21 -0
- data/lib/rdoc/markup/formatter.rb +220 -203
- data/lib/rdoc/markup/hard_break.rb +30 -27
- data/lib/rdoc/markup/heading.rb +163 -77
- data/lib/rdoc/markup/include.rb +33 -29
- data/lib/rdoc/markup/indented_paragraph.rb +37 -33
- data/lib/rdoc/markup/inline_parser.rb +316 -0
- data/lib/rdoc/markup/list.rb +80 -88
- data/lib/rdoc/markup/list_item.rb +73 -85
- data/lib/rdoc/markup/paragraph.rb +23 -19
- data/lib/rdoc/markup/parser.rb +501 -497
- data/lib/rdoc/markup/pre_process.rb +284 -305
- data/lib/rdoc/markup/raw.rb +52 -55
- data/lib/rdoc/markup/rule.rb +16 -12
- data/lib/rdoc/markup/table.rb +48 -40
- data/lib/rdoc/markup/to_ansi.rb +143 -92
- data/lib/rdoc/markup/to_bs.rb +86 -102
- data/lib/rdoc/markup/to_html.rb +608 -506
- data/lib/rdoc/markup/to_html_crossref.rb +219 -210
- data/lib/rdoc/markup/to_html_snippet.rb +210 -205
- data/lib/rdoc/markup/to_joined_paragraph.rb +40 -41
- data/lib/rdoc/markup/to_label.rb +64 -51
- data/lib/rdoc/markup/to_markdown.rb +212 -184
- data/lib/rdoc/markup/to_rdoc.rb +341 -277
- data/lib/rdoc/markup/to_table_of_contents.rb +66 -62
- data/lib/rdoc/markup/to_test.rb +62 -50
- data/lib/rdoc/markup/to_tt_only.rb +83 -92
- data/lib/rdoc/markup/verbatim.rb +62 -58
- data/lib/rdoc/markup.rb +196 -215
- data/lib/rdoc/options.rb +1063 -1076
- data/lib/rdoc/parser/c.rb +1039 -1036
- data/lib/rdoc/parser/changelog.rb +320 -287
- data/lib/rdoc/parser/markdown.rb +17 -13
- data/lib/rdoc/parser/rbs.rb +279 -0
- data/lib/rdoc/parser/rd.rb +17 -13
- data/lib/rdoc/parser/ruby.rb +1231 -2222
- data/lib/rdoc/parser/ruby_colorizer.rb +303 -0
- data/lib/rdoc/parser/simple.rb +31 -27
- data/lib/rdoc/parser/text.rb +12 -8
- data/lib/rdoc/parser.rb +230 -221
- data/lib/rdoc/rbs_helper.rb +186 -0
- data/lib/rdoc/rd/inline.rb +57 -53
- data/lib/rdoc/rd.rb +90 -88
- data/lib/rdoc/rdoc.rb +547 -366
- data/lib/rdoc/ri/driver.rb +1141 -1130
- data/lib/rdoc/ri/formatter.rb +7 -3
- data/lib/rdoc/ri/paths.rb +140 -136
- data/lib/rdoc/ri/servlet.rb +456 -0
- data/lib/rdoc/ri/store.rb +4 -2
- data/lib/rdoc/ri/task.rb +55 -51
- data/lib/rdoc/ri.rb +14 -11
- data/lib/rdoc/rubygems_hook.rb +194 -192
- data/lib/rdoc/server.rb +462 -0
- data/lib/rdoc/stats/normal.rb +46 -42
- data/lib/rdoc/stats/quiet.rb +39 -35
- data/lib/rdoc/stats/verbose.rb +35 -31
- data/lib/rdoc/stats.rb +363 -338
- data/lib/rdoc/store.rb +919 -725
- data/lib/rdoc/task.rb +260 -255
- data/lib/rdoc/text.rb +164 -240
- data/lib/rdoc/token_stream.rb +88 -106
- data/lib/rdoc/tom_doc.rb +203 -201
- data/lib/rdoc/version.rb +1 -1
- data/lib/rdoc.rb +35 -7
- data/lib/rubygems_plugin.rb +2 -11
- data/rdoc-logo.svg +43 -0
- data/rdoc.gemspec +9 -7
- metadata +46 -32
- data/CONTRIBUTING.rdoc +0 -219
- data/ExampleMarkdown.md +0 -39
- data/ExampleRDoc.rdoc +0 -210
- data/lib/rdoc/code_object/anon_class.rb +0 -10
- data/lib/rdoc/code_object/ghost_method.rb +0 -6
- data/lib/rdoc/code_object/meta_method.rb +0 -6
- data/lib/rdoc/markdown/literals.kpeg +0 -21
- data/lib/rdoc/markdown/literals.rb +0 -454
- data/lib/rdoc/markup/attr_changer.rb +0 -22
- data/lib/rdoc/markup/attr_span.rb +0 -35
- data/lib/rdoc/markup/attribute_manager.rb +0 -405
- data/lib/rdoc/markup/attributes.rb +0 -70
- data/lib/rdoc/markup/regexp_handling.rb +0 -40
- data/lib/rdoc/parser/prism_ruby.rb +0 -1100
- data/lib/rdoc/parser/ripper_state_lex.rb +0 -302
- data/lib/rdoc/parser/ruby_tools.rb +0 -163
- data/lib/rdoc/servlet.rb +0 -452
|
@@ -28,7 +28,7 @@ function createSearchInstance(input, result) {
|
|
|
28
28
|
|
|
29
29
|
result.classList.remove("initially-hidden");
|
|
30
30
|
|
|
31
|
-
const search = new
|
|
31
|
+
const search = new SearchController(search_data, input, result);
|
|
32
32
|
|
|
33
33
|
search.renderItem = function(result) {
|
|
34
34
|
const li = document.createElement('li');
|
|
@@ -40,8 +40,14 @@ function createSearchInstance(input, result) {
|
|
|
40
40
|
html += `<span class="params">${result.params}</span>`;
|
|
41
41
|
html += '</a>';
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
// Add type indicator
|
|
44
|
+
if (result.type) {
|
|
45
|
+
const typeLabel = this.formatType(result.type);
|
|
46
|
+
const typeClass = result.type.replace(/_/g, '-');
|
|
47
|
+
html += `<span class="search-type search-type-${this.escapeHTML(typeClass)}">${typeLabel}</span>`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
html += '</p>';
|
|
45
51
|
|
|
46
52
|
if (result.snippet)
|
|
47
53
|
html += `<div class="search-snippet">${result.snippet}</div>`;
|
|
@@ -51,19 +57,20 @@ function createSearchInstance(input, result) {
|
|
|
51
57
|
return li;
|
|
52
58
|
}
|
|
53
59
|
|
|
54
|
-
search.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
window.location.href = href;
|
|
60
|
+
search.formatType = function(type) {
|
|
61
|
+
const typeLabels = {
|
|
62
|
+
'class': 'class',
|
|
63
|
+
'module': 'module',
|
|
64
|
+
'constant': 'const',
|
|
65
|
+
'instance_method': 'method',
|
|
66
|
+
'class_method': 'method'
|
|
67
|
+
};
|
|
68
|
+
return typeLabels[type] || type;
|
|
64
69
|
}
|
|
65
70
|
|
|
66
|
-
search.
|
|
71
|
+
search.select = function(result) {
|
|
72
|
+
window.location.href = result.firstChild.firstChild.href;
|
|
73
|
+
}
|
|
67
74
|
|
|
68
75
|
return search;
|
|
69
76
|
}
|
|
@@ -74,6 +81,11 @@ function hookSearch() {
|
|
|
74
81
|
|
|
75
82
|
if (!input || !result) return; // Exit if search elements not found
|
|
76
83
|
|
|
84
|
+
const container = input.closest('[data-search-container]');
|
|
85
|
+
const searchToggle = document.querySelector('#search-toggle');
|
|
86
|
+
const searchEmpty = container && container.querySelector('.search-empty');
|
|
87
|
+
let focusBeforeOpen = null;
|
|
88
|
+
|
|
77
89
|
const search_section = document.querySelector('#search-section');
|
|
78
90
|
if (search_section) {
|
|
79
91
|
search_section.classList.remove("initially-hidden");
|
|
@@ -82,29 +94,92 @@ function hookSearch() {
|
|
|
82
94
|
const search = createSearchInstance(input, result);
|
|
83
95
|
if (!search) return;
|
|
84
96
|
|
|
97
|
+
if (searchEmpty) {
|
|
98
|
+
const originalRenderItem = search.renderItem;
|
|
99
|
+
search.renderItem = function(result) {
|
|
100
|
+
searchEmpty.style.display = 'none';
|
|
101
|
+
return originalRenderItem.call(this, result);
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const showSearchSurface = () => {
|
|
106
|
+
if (container) container.classList.add('is-open');
|
|
107
|
+
if (searchToggle) searchToggle.setAttribute('aria-expanded', 'true');
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const openSearch = () => {
|
|
111
|
+
focusBeforeOpen = document.activeElement;
|
|
112
|
+
showSearchSurface();
|
|
113
|
+
input.focus({ preventScroll: true });
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const closeSearch = (restoreFocus = true) => {
|
|
117
|
+
if (container) container.classList.remove('is-open');
|
|
118
|
+
if (searchToggle) searchToggle.setAttribute('aria-expanded', 'false');
|
|
119
|
+
search.hide();
|
|
120
|
+
input.blur();
|
|
121
|
+
|
|
122
|
+
if (restoreFocus && focusBeforeOpen && typeof focusBeforeOpen.focus === 'function') {
|
|
123
|
+
focusBeforeOpen.focus({ preventScroll: true });
|
|
124
|
+
}
|
|
125
|
+
focusBeforeOpen = null;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
if (searchToggle) searchToggle.addEventListener('click', openSearch);
|
|
129
|
+
if (container) {
|
|
130
|
+
container.querySelectorAll('[data-search-close]').forEach((control) => {
|
|
131
|
+
control.addEventListener('click', () => closeSearch());
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
hookFocus(openSearch);
|
|
136
|
+
|
|
137
|
+
// Hide search results when clicking outside the search area
|
|
138
|
+
document.addEventListener('click', (e) => {
|
|
139
|
+
if (container && container.contains(e.target)) return;
|
|
140
|
+
|
|
141
|
+
search.hide();
|
|
142
|
+
if (container && container.classList.contains('is-open')) closeSearch(false);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// Close the search surface on Escape
|
|
146
|
+
document.addEventListener('keydown', (e) => {
|
|
147
|
+
const isOpen = container && container.classList.contains('is-open');
|
|
148
|
+
if (e.key === 'Escape' && (isOpen || input.matches(":focus"))) {
|
|
149
|
+
closeSearch();
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// Show search results when focusing on input (if there's a query)
|
|
154
|
+
input.addEventListener('focus', () => {
|
|
155
|
+
showSearchSurface();
|
|
156
|
+
if (input.value.trim()) {
|
|
157
|
+
search.show();
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
85
161
|
// Check for ?q= URL parameter and trigger search automatically
|
|
86
162
|
if (typeof URLSearchParams !== 'undefined') {
|
|
87
163
|
const urlParams = new URLSearchParams(window.location.search);
|
|
88
164
|
const queryParam = urlParams.get('q');
|
|
89
165
|
if (queryParam) {
|
|
90
|
-
|
|
91
|
-
const autoSelect = navParam !== '0';
|
|
166
|
+
openSearch();
|
|
92
167
|
input.value = queryParam;
|
|
93
|
-
search.search(queryParam,
|
|
168
|
+
search.search(queryParam, false);
|
|
94
169
|
}
|
|
95
170
|
}
|
|
96
171
|
}
|
|
97
172
|
|
|
98
173
|
/* ===== Keyboard Shortcuts ===== */
|
|
99
174
|
|
|
100
|
-
function hookFocus() {
|
|
175
|
+
function hookFocus(openSearch) {
|
|
101
176
|
document.addEventListener("keydown", (event) => {
|
|
102
177
|
if (document.activeElement.tagName === 'INPUT') {
|
|
103
178
|
return;
|
|
104
179
|
}
|
|
105
180
|
if (event.key === "/") {
|
|
106
181
|
event.preventDefault();
|
|
107
|
-
|
|
182
|
+
openSearch();
|
|
108
183
|
}
|
|
109
184
|
});
|
|
110
185
|
}
|
|
@@ -112,55 +187,62 @@ function hookFocus() {
|
|
|
112
187
|
/* ===== Mobile Navigation ===== */
|
|
113
188
|
|
|
114
189
|
function hookSidebar() {
|
|
115
|
-
const
|
|
116
|
-
const
|
|
190
|
+
const sidebarNavigation = document.querySelector('#sidebar-navigation');
|
|
191
|
+
const sidebarNavigationToggle = document.querySelector('#sidebar-navigation-toggle');
|
|
117
192
|
|
|
118
|
-
if (!
|
|
193
|
+
if (!sidebarNavigation || !sidebarNavigationToggle) return;
|
|
119
194
|
|
|
120
195
|
const closeNav = () => {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
document.body.classList.remove('
|
|
196
|
+
sidebarNavigation.hidden = true;
|
|
197
|
+
sidebarNavigationToggle.ariaExpanded = 'false';
|
|
198
|
+
document.body.classList.remove('sidebar-navigation-open');
|
|
124
199
|
};
|
|
125
200
|
|
|
126
201
|
const openNav = () => {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
document.body.classList.add('
|
|
202
|
+
sidebarNavigation.hidden = false;
|
|
203
|
+
sidebarNavigationToggle.ariaExpanded = 'true';
|
|
204
|
+
document.body.classList.add('sidebar-navigation-open');
|
|
130
205
|
};
|
|
131
206
|
|
|
132
207
|
const toggleNav = () => {
|
|
133
|
-
if (
|
|
208
|
+
if (sidebarNavigation.hidden) {
|
|
134
209
|
openNav();
|
|
135
210
|
} else {
|
|
136
211
|
closeNav();
|
|
137
212
|
}
|
|
138
213
|
};
|
|
139
214
|
|
|
140
|
-
|
|
215
|
+
sidebarNavigationToggle.addEventListener('click', (e) => {
|
|
141
216
|
e.stopPropagation();
|
|
142
217
|
toggleNav();
|
|
143
218
|
});
|
|
144
219
|
|
|
145
220
|
const isSmallViewport = window.matchMedia("(max-width: 1023px)").matches;
|
|
221
|
+
|
|
222
|
+
// The sidebar is hidden by default with the `hidden` attribute
|
|
223
|
+
// On large viewports, we display the sidebar with JavaScript
|
|
224
|
+
// This is better than the opposite approach of hiding it with JavaScript
|
|
225
|
+
// because it avoids flickering the sidebar when the page is loaded, especially on mobile devices
|
|
146
226
|
if (isSmallViewport) {
|
|
147
227
|
closeNav();
|
|
148
228
|
|
|
149
229
|
// Close nav when clicking links inside it
|
|
150
230
|
document.addEventListener('click', (e) => {
|
|
151
|
-
if (e.target.closest('#navigation a')) {
|
|
231
|
+
if (e.target.closest('#sidebar-navigation a')) {
|
|
152
232
|
closeNav();
|
|
153
233
|
}
|
|
154
234
|
});
|
|
155
235
|
|
|
156
236
|
// Close nav when clicking backdrop
|
|
157
237
|
document.addEventListener('click', (e) => {
|
|
158
|
-
if (!
|
|
159
|
-
!e.target.closest('#navigation') &&
|
|
160
|
-
!e.target.closest('#navigation-toggle')) {
|
|
238
|
+
if (!sidebarNavigation.hidden &&
|
|
239
|
+
!e.target.closest('#sidebar-navigation') &&
|
|
240
|
+
!e.target.closest('#sidebar-navigation-toggle')) {
|
|
161
241
|
closeNav();
|
|
162
242
|
}
|
|
163
243
|
});
|
|
244
|
+
} else {
|
|
245
|
+
openNav();
|
|
164
246
|
}
|
|
165
247
|
}
|
|
166
248
|
|
|
@@ -203,7 +285,7 @@ function generateToc() {
|
|
|
203
285
|
tocNav.appendChild(tocList);
|
|
204
286
|
} else {
|
|
205
287
|
// Hide TOC if no headings found
|
|
206
|
-
const tocContainer = document.querySelector('
|
|
288
|
+
const tocContainer = document.querySelector('#table-of-contents');
|
|
207
289
|
if (tocContainer) {
|
|
208
290
|
tocContainer.style.display = 'none';
|
|
209
291
|
}
|
|
@@ -296,80 +378,6 @@ function setHeadingSelfLinkScrollHandlers() {
|
|
|
296
378
|
})
|
|
297
379
|
}
|
|
298
380
|
|
|
299
|
-
/* ===== Mobile Search Modal ===== */
|
|
300
|
-
|
|
301
|
-
function hookSearchModal() {
|
|
302
|
-
const searchToggle = document.querySelector('#search-toggle');
|
|
303
|
-
const searchModal = document.querySelector('#search-modal');
|
|
304
|
-
const searchModalClose = document.querySelector('#search-modal-close');
|
|
305
|
-
const searchModalBackdrop = document.querySelector('.search-modal-backdrop');
|
|
306
|
-
const searchInput = document.querySelector('#search-field-mobile');
|
|
307
|
-
const searchResults = document.querySelector('#search-results-mobile');
|
|
308
|
-
const searchEmpty = document.querySelector('.search-modal-empty');
|
|
309
|
-
|
|
310
|
-
if (!searchToggle || !searchModal) return;
|
|
311
|
-
|
|
312
|
-
// Initialize search for mobile modal
|
|
313
|
-
const mobileSearch = createSearchInstance(searchInput, searchResults);
|
|
314
|
-
if (!mobileSearch) return;
|
|
315
|
-
|
|
316
|
-
// Hide empty state when there are results
|
|
317
|
-
const originalRenderItem = mobileSearch.renderItem;
|
|
318
|
-
mobileSearch.renderItem = function(result) {
|
|
319
|
-
if (searchEmpty) searchEmpty.style.display = 'none';
|
|
320
|
-
return originalRenderItem.call(this, result);
|
|
321
|
-
};
|
|
322
|
-
|
|
323
|
-
const openSearchModal = () => {
|
|
324
|
-
searchModal.hidden = false;
|
|
325
|
-
document.body.style.overflow = 'hidden';
|
|
326
|
-
// Focus input after animation
|
|
327
|
-
setTimeout(() => {
|
|
328
|
-
if (searchInput) searchInput.focus();
|
|
329
|
-
}, 100);
|
|
330
|
-
};
|
|
331
|
-
|
|
332
|
-
const closeSearchModal = () => {
|
|
333
|
-
searchModal.hidden = true;
|
|
334
|
-
document.body.style.overflow = '';
|
|
335
|
-
};
|
|
336
|
-
|
|
337
|
-
// Open on button click
|
|
338
|
-
searchToggle.addEventListener('click', openSearchModal);
|
|
339
|
-
|
|
340
|
-
// Close on close button click
|
|
341
|
-
if (searchModalClose) {
|
|
342
|
-
searchModalClose.addEventListener('click', closeSearchModal);
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
// Close on backdrop click
|
|
346
|
-
if (searchModalBackdrop) {
|
|
347
|
-
searchModalBackdrop.addEventListener('click', closeSearchModal);
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
// Close on Escape key
|
|
351
|
-
document.addEventListener('keydown', (e) => {
|
|
352
|
-
if (e.key === 'Escape' && !searchModal.hidden) {
|
|
353
|
-
closeSearchModal();
|
|
354
|
-
}
|
|
355
|
-
});
|
|
356
|
-
|
|
357
|
-
// Check for ?q= URL parameter on mobile and open modal
|
|
358
|
-
if (typeof URLSearchParams !== 'undefined') {
|
|
359
|
-
const urlParams = new URLSearchParams(window.location.search);
|
|
360
|
-
const queryParam = urlParams.get('q');
|
|
361
|
-
const isSmallViewport = window.matchMedia("(max-width: 1023px)").matches;
|
|
362
|
-
|
|
363
|
-
if (queryParam && isSmallViewport) {
|
|
364
|
-
openSearchModal();
|
|
365
|
-
searchInput.value = queryParam;
|
|
366
|
-
const navParam = urlParams.get('nav');
|
|
367
|
-
const autoSelect = navParam !== '0';
|
|
368
|
-
mobileSearch.search(queryParam, autoSelect);
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
|
|
373
381
|
/* ===== Code Block Copy Functionality ===== */
|
|
374
382
|
|
|
375
383
|
function createCopyButton() {
|
|
@@ -407,8 +415,8 @@ function wrapCodeBlocksWithCopyButton() {
|
|
|
407
415
|
// not directly in rhtml templates
|
|
408
416
|
// - Modifying the formatter would require extending RDoc's core internals
|
|
409
417
|
|
|
410
|
-
//
|
|
411
|
-
const preElements = document.querySelectorAll('main pre:not(.
|
|
418
|
+
// Target code examples and source code; skip type signature blocks
|
|
419
|
+
const preElements = document.querySelectorAll('main pre:not(.method-type-signature)');
|
|
412
420
|
|
|
413
421
|
preElements.forEach((pre) => {
|
|
414
422
|
// Skip if already wrapped
|
|
@@ -473,11 +481,9 @@ function showCopySuccess(button) {
|
|
|
473
481
|
document.addEventListener('DOMContentLoaded', () => {
|
|
474
482
|
hookSourceViews();
|
|
475
483
|
hookSearch();
|
|
476
|
-
hookFocus();
|
|
477
484
|
hookSidebar();
|
|
478
485
|
generateToc();
|
|
479
486
|
setHeadingSelfLinkScrollHandlers();
|
|
480
487
|
hookTocActiveHighlighting();
|
|
481
|
-
hookSearchModal();
|
|
482
488
|
wrapCodeBlocksWithCopyButton();
|
|
483
489
|
});
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side shell syntax highlighter for RDoc
|
|
3
|
+
* Highlights: $ prompts, commands, options, strings, env vars, comments
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
(function() {
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
function escapeHtml(text) {
|
|
10
|
+
return text
|
|
11
|
+
.replace(/&/g, '&')
|
|
12
|
+
.replace(/</g, '<')
|
|
13
|
+
.replace(/>/g, '>')
|
|
14
|
+
.replace(/"/g, '"')
|
|
15
|
+
.replace(/'/g, ''');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function wrap(className, text) {
|
|
19
|
+
return '<span class="' + className + '">' + escapeHtml(text) + '</span>';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function highlightLine(line) {
|
|
23
|
+
if (line.trim() === '') return escapeHtml(line);
|
|
24
|
+
|
|
25
|
+
var result = '';
|
|
26
|
+
var i = 0;
|
|
27
|
+
var len = line.length;
|
|
28
|
+
|
|
29
|
+
// Preserve leading whitespace
|
|
30
|
+
while (i < len && (line[i] === ' ' || line[i] === '\t')) {
|
|
31
|
+
result += escapeHtml(line[i++]);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Check for $ prompt ($ followed by space or end of line)
|
|
35
|
+
if (line[i] === '$' && (line[i + 1] === ' ' || line[i + 1] === undefined)) {
|
|
36
|
+
result += wrap('sh-prompt', '$');
|
|
37
|
+
i++;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Check for # comment at start
|
|
41
|
+
if (line[i] === '#') {
|
|
42
|
+
return result + wrap('sh-comment', line.slice(i));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
var seenCommand = false;
|
|
46
|
+
var afterSpace = true;
|
|
47
|
+
|
|
48
|
+
while (i < len) {
|
|
49
|
+
var ch = line[i];
|
|
50
|
+
|
|
51
|
+
// Whitespace
|
|
52
|
+
if (ch === ' ' || ch === '\t') {
|
|
53
|
+
result += escapeHtml(ch);
|
|
54
|
+
i++;
|
|
55
|
+
afterSpace = true;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Comment after whitespace
|
|
60
|
+
if (ch === '#' && afterSpace) {
|
|
61
|
+
result += wrap('sh-comment', line.slice(i));
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Double-quoted string
|
|
66
|
+
if (ch === '"') {
|
|
67
|
+
var end = i + 1;
|
|
68
|
+
while (end < len && line[end] !== '"') {
|
|
69
|
+
if (line[end] === '\\' && end + 1 < len) end += 2;
|
|
70
|
+
else end++;
|
|
71
|
+
}
|
|
72
|
+
if (end < len) end++;
|
|
73
|
+
result += wrap('sh-string', line.slice(i, end));
|
|
74
|
+
i = end;
|
|
75
|
+
afterSpace = false;
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Single-quoted string
|
|
80
|
+
if (ch === "'") {
|
|
81
|
+
var end = i + 1;
|
|
82
|
+
while (end < len && line[end] !== "'") end++;
|
|
83
|
+
if (end < len) end++;
|
|
84
|
+
result += wrap('sh-string', line.slice(i, end));
|
|
85
|
+
i = end;
|
|
86
|
+
afterSpace = false;
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Environment variable (ALLCAPS=)
|
|
91
|
+
if (afterSpace && /[A-Z]/.test(ch)) {
|
|
92
|
+
var match = line.slice(i).match(/^[A-Z][A-Z0-9_]*=/);
|
|
93
|
+
if (match) {
|
|
94
|
+
result += wrap('sh-envvar', match[0]);
|
|
95
|
+
i += match[0].length;
|
|
96
|
+
// Read unquoted value
|
|
97
|
+
var valEnd = i;
|
|
98
|
+
while (valEnd < len && line[valEnd] !== ' ' && line[valEnd] !== '\t' && line[valEnd] !== '"' && line[valEnd] !== "'") valEnd++;
|
|
99
|
+
if (valEnd > i) {
|
|
100
|
+
result += escapeHtml(line.slice(i, valEnd));
|
|
101
|
+
i = valEnd;
|
|
102
|
+
}
|
|
103
|
+
afterSpace = false;
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Option (must be after whitespace)
|
|
109
|
+
if (ch === '-' && afterSpace) {
|
|
110
|
+
var match = line.slice(i).match(/^--?[a-zA-Z0-9_-]+(=[^"'\s]*)?/);
|
|
111
|
+
if (match) {
|
|
112
|
+
result += wrap('sh-option', match[0]);
|
|
113
|
+
i += match[0].length;
|
|
114
|
+
afterSpace = false;
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Command (first word: regular, ./path, ../path, ~/path, /abs/path, @scope/pkg)
|
|
120
|
+
if (!seenCommand && afterSpace) {
|
|
121
|
+
var isCmd = /[a-zA-Z0-9@~\/]/.test(ch) ||
|
|
122
|
+
(ch === '.' && (line[i + 1] === '/' || (line[i + 1] === '.' && line[i + 2] === '/')));
|
|
123
|
+
if (isCmd) {
|
|
124
|
+
var end = i;
|
|
125
|
+
while (end < len && line[end] !== ' ' && line[end] !== '\t') end++;
|
|
126
|
+
result += wrap('sh-command', line.slice(i, end));
|
|
127
|
+
i = end;
|
|
128
|
+
seenCommand = true;
|
|
129
|
+
afterSpace = false;
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Everything else
|
|
135
|
+
result += escapeHtml(ch);
|
|
136
|
+
i++;
|
|
137
|
+
afterSpace = false;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return result;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function highlightShell(code) {
|
|
144
|
+
return code.split('\n').map(highlightLine).join('\n');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function initHighlighting() {
|
|
148
|
+
var selectors = [
|
|
149
|
+
'pre.bash', 'pre.sh', 'pre.shell', 'pre.console',
|
|
150
|
+
'pre[data-language="bash"]', 'pre[data-language="sh"]',
|
|
151
|
+
'pre[data-language="shell"]', 'pre[data-language="console"]'
|
|
152
|
+
];
|
|
153
|
+
|
|
154
|
+
var blocks = document.querySelectorAll(selectors.join(', '));
|
|
155
|
+
blocks.forEach(function(block) {
|
|
156
|
+
if (block.getAttribute('data-highlighted') === 'true') return;
|
|
157
|
+
block.innerHTML = highlightShell(block.textContent);
|
|
158
|
+
block.setAttribute('data-highlighted', 'true');
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (document.readyState === 'loading') {
|
|
163
|
+
document.addEventListener('DOMContentLoaded', initHighlighting);
|
|
164
|
+
} else {
|
|
165
|
+
initHighlighting();
|
|
166
|
+
}
|
|
167
|
+
})();
|
|
@@ -276,7 +276,7 @@
|
|
|
276
276
|
* Initialize C syntax highlighting on page load
|
|
277
277
|
*/
|
|
278
278
|
function initHighlighting() {
|
|
279
|
-
const codeBlocks = document.querySelectorAll('pre
|
|
279
|
+
const codeBlocks = document.querySelectorAll('pre.c');
|
|
280
280
|
|
|
281
281
|
codeBlocks.forEach(block => {
|
|
282
282
|
if (block.getAttribute('data-highlighted') === 'true') {
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
SearchController = function(data, input, result) {
|
|
2
2
|
this.data = data;
|
|
3
3
|
this.input = input;
|
|
4
4
|
this.result = result;
|
|
5
5
|
|
|
6
6
|
this.current = null;
|
|
7
7
|
this.view = this.result.parentNode;
|
|
8
|
-
this.
|
|
8
|
+
this.ranker = new SearchRanker(data.index);
|
|
9
9
|
this.init();
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
SearchController.prototype = Object.assign({}, SearchNavigation, new function() {
|
|
13
13
|
var suid = 1;
|
|
14
14
|
|
|
15
15
|
this.init = function() {
|
|
@@ -25,7 +25,7 @@ Search.prototype = Object.assign({}, Navigation, new function() {
|
|
|
25
25
|
this.input.addEventListener('keyup', observer);
|
|
26
26
|
this.input.addEventListener('click', observer); // mac's clear field
|
|
27
27
|
|
|
28
|
-
this.
|
|
28
|
+
this.ranker.ready(function(results, isLast) {
|
|
29
29
|
_this.addResults(results, isLast);
|
|
30
30
|
})
|
|
31
31
|
|
|
@@ -36,7 +36,7 @@ Search.prototype = Object.assign({}, Navigation, new function() {
|
|
|
36
36
|
this.search = function(value, selectFirstMatch) {
|
|
37
37
|
this.selectFirstMatch = selectFirstMatch;
|
|
38
38
|
|
|
39
|
-
value = value.trim()
|
|
39
|
+
value = value.trim();
|
|
40
40
|
if (value) {
|
|
41
41
|
this.setNavigationActive(true);
|
|
42
42
|
} else {
|
|
@@ -53,7 +53,7 @@ Search.prototype = Object.assign({}, Navigation, new function() {
|
|
|
53
53
|
this.result.setAttribute('aria-busy', 'true');
|
|
54
54
|
this.result.setAttribute('aria-expanded', 'true');
|
|
55
55
|
this.firstRun = true;
|
|
56
|
-
this.
|
|
56
|
+
this.ranker.find(value);
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
|
|
@@ -96,7 +96,7 @@ Search.prototype = Object.assign({}, Navigation, new function() {
|
|
|
96
96
|
this.current.classList.remove('search-selected');
|
|
97
97
|
next.classList.add('search-selected');
|
|
98
98
|
this.input.setAttribute('aria-activedescendant', next.getAttribute('id'));
|
|
99
|
-
this.
|
|
99
|
+
this.scrollInElement(next, this.result);
|
|
100
100
|
this.current = next;
|
|
101
101
|
this.input.value = next.firstChild.firstChild.text;
|
|
102
102
|
this.input.select();
|
|
@@ -116,5 +116,14 @@ Search.prototype = Object.assign({}, Navigation, new function() {
|
|
|
116
116
|
});
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
this.hide = function() {
|
|
120
|
+
this.result.setAttribute('aria-expanded', 'false');
|
|
121
|
+
this.setNavigationActive(false);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
this.show = function() {
|
|
125
|
+
this.result.setAttribute('aria-expanded', 'true');
|
|
126
|
+
this.setNavigationActive(true);
|
|
127
|
+
}
|
|
119
128
|
});
|
|
120
129
|
|