Skip to content

Commit 8b94ea6

Browse files
ShogunPandasxa
authored andcommitted
doc,tools: improve navigability of API docs
PR-URL: #41404 Reviewed-By: Rich Trott <[email protected]> Reviewed-By: Antoine du Hamel <[email protected]>
1 parent 86248f1 commit 8b94ea6

File tree

4 files changed

+205
-40
lines changed

4 files changed

+205
-40
lines changed

doc/api_assets/style.css

+117-13
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ em code {
162162
margin-bottom: 1rem;
163163
}
164164

165-
#gtoc ul {
165+
#gtoc > ul {
166166
list-style: none;
167167
margin-left: 0;
168168
line-height: 1.5rem;
@@ -172,60 +172,106 @@ em code {
172172
color: var(--color-critical);
173173
}
174174

175-
li.version-picker {
175+
li.picker-header {
176176
position: relative;
177177
}
178178

179-
li.version-picker:hover > a {
179+
li.picker-header .collapsed-arrow, li.picker-header .expanded-arrow {
180+
width: 1.5ch;
181+
height: 1.5em;
182+
}
183+
184+
li.picker-header .collapsed-arrow {
185+
display: inline-block;
186+
}
187+
188+
li.picker-header .expanded-arrow {
189+
display: none;
190+
}
191+
192+
li.picker-header:hover .collapsed-arrow {
193+
display: none;
194+
}
195+
196+
li.picker-header:hover .expanded-arrow {
197+
display: inline-block;
198+
}
199+
200+
li.picker-header:hover > a {
180201
border-radius: 2px 2px 0 0;
181202
}
182203

183-
li.version-picker:hover > ol {
204+
li.picker-header:hover > .picker {
184205
display: block;
185206
z-index: 1;
186207
}
187208

188-
li.version-picker a span {
209+
li.picker-header a span {
189210
font-size: .7rem;
190211
}
191212

192-
ol.version-picker {
213+
.picker {
193214
background-color: var(--color-fill-app);
194215
border: 1px solid var(--color-brand-secondary);
195216
border-radius: 0 0 2px 2px;
196217
display: none;
197218
list-style: none;
198219
position: absolute;
199-
right: 0;
220+
left: 0;
200221
top: 100%;
201-
width: 100%;
222+
width: max-content;
223+
min-width: min(300px, 75vw);
224+
max-width: 75vw;
225+
max-height: min(600px, 60vh);
226+
overflow-y: auto;
202227
}
203228

204-
#gtoc ol.version-picker li {
229+
.picker > ul, .picker > ol {
230+
list-style: none;
231+
margin-left: 0;
232+
line-height: 1.5rem;
233+
}
234+
235+
.picker li {
205236
display: block;
206237
border-right: 0;
207238
margin-right: 0;
208239
}
209240

210-
ol.version-picker li a {
241+
.picker li a {
211242
border-radius: 0;
212243
display: block;
213244
margin: 0;
214245
padding: .1rem;
215246
padding-left: 1rem;
216247
}
217248

218-
ol.version-picker li:last-child a {
249+
.picker li a.active,
250+
.picker li a.active:hover,
251+
.picker li a.active:focus {
252+
font-weight: 700;
253+
}
254+
255+
.picker li:last-child a {
219256
border-bottom-right-radius: 1px;
220257
border-bottom-left-radius: 1px;
221258
}
222259

260+
.gtoc-picker-header {
261+
display: none;
262+
}
263+
223264
.line {
224265
width: calc(100% - 1rem);
225266
display: block;
226267
padding-bottom: 1px;
227268
}
228269

270+
.picker .line {
271+
margin: 0;
272+
width: 100%;
273+
}
274+
229275
.api_stability {
230276
color: var(--white) !important;
231277
margin: 0 0 1rem;
@@ -506,6 +552,41 @@ hr {
506552
margin-top: .666rem;
507553
}
508554

555+
.toc ul {
556+
margin: 0
557+
}
558+
559+
.toc li a::before {
560+
content: "■";
561+
color: var(--color-text-primary);
562+
padding-right: 1em;
563+
font-size: 0.9em;
564+
}
565+
566+
.toc li a:hover::before {
567+
color: var(--white);
568+
}
569+
570+
.toc ul ul a {
571+
padding-left: 1rem;
572+
}
573+
574+
.toc ul ul ul a {
575+
padding-left: 2rem;
576+
}
577+
578+
.toc ul ul ul ul a {
579+
padding-left: 3rem;
580+
}
581+
582+
.toc ul ul ul ul ul a {
583+
padding-left: 4rem;
584+
}
585+
586+
.toc ul ul ul ul ul ul a {
587+
padding-left: 5rem;
588+
}
589+
509590
#toc .stability_0::after {
510591
background-color: var(--red2);
511592
color: var(--white);
@@ -718,10 +799,25 @@ kbd {
718799
}
719800
}
720801

802+
.header {
803+
position: sticky;
804+
top: -1px;
805+
z-index: 1;
806+
padding-top: 1rem;
807+
background-color: var(--color-fill-app);
808+
}
809+
810+
@media not screen, (max-height: 1000px) {
811+
.header {
812+
position: relative;
813+
top: 0;
814+
}
815+
}
816+
721817
.header-container {
722818
display: flex;
723819
align-items: center;
724-
margin: 1.5rem 0 1rem;
820+
margin-bottom: 1rem;
725821
justify-content: space-between;
726822
}
727823

@@ -735,7 +831,7 @@ kbd {
735831
outline: var(--brand3) dotted 2px;
736832
}
737833

738-
@media only screen and (min-width: 577px) {
834+
@media only screen and (min-width: 601px) {
739835
#gtoc > ul > li {
740836
display: inline;
741837
border-right: 1px currentColor solid;
@@ -748,6 +844,10 @@ kbd {
748844
margin-right: 0;
749845
padding-right: 0;
750846
}
847+
848+
#gtoc > ul > li.gtoc-picker-header {
849+
display: none;
850+
}
751851
}
752852

753853
@media only screen and (max-width: 1024px) {
@@ -764,6 +864,10 @@ kbd {
764864
#column2 {
765865
display: none;
766866
}
867+
868+
#gtoc > ul > li.gtoc-picker-header {
869+
display: inline;
870+
}
767871
}
768872

769873
.icon {

doc/template.html

+21-11
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
</div>
2323

2424
<div id="column1" data-id="__ID__" class="interior">
25-
<header>
25+
<header class="header">
2626
<div class="header-container">
2727
<h1>Node.js __VERSION__ documentation</h1>
2828
<button class="theme-toggle-btn" id="theme-toggle-btn" title="Toggle dark mode/light mode" aria-label="Toggle dark mode/light mode" hidden>
@@ -39,17 +39,27 @@ <h1>Node.js __VERSION__ documentation</h1>
3939
</div>
4040
<div id="gtoc">
4141
<ul>
42-
<li>
43-
<a href="index.html">Index</a>
44-
</li>
45-
<li>
46-
<a href="all.html">View on single page</a>
47-
</li>
48-
<li>
49-
<a href="__FILENAME__.json">View as JSON</a>
50-
</li>
42+
__TOC_PICKER__
43+
__GTOC_PICKER__
5144
__ALTDOCS__
52-
__EDIT_ON_GITHUB__
45+
<li class="picker-header">
46+
<a href="#">
47+
<span class="collapsed-arrow">&#x25ba;</span><span class="expanded-arrow">&#x25bc;</span>
48+
Options
49+
</a>
50+
51+
<div class="picker">
52+
<ul>
53+
<li>
54+
<a href="all.html">View on single page</a>
55+
</li>
56+
<li>
57+
<a href="__FILENAME__.json">View as JSON</a>
58+
</li>
59+
__EDIT_ON_GITHUB__
60+
</ul>
61+
</div>
62+
</li>
5363
</ul>
5464
</div>
5565
<hr>

test/doctool/test-make-doc.mjs

+2-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ const links = toc.match(globalRe);
4040
assert.notStrictEqual(links, null);
4141

4242
// Filter out duplicate links, leave just filenames, add expected JSON files.
43-
const linkedHtmls = [...new Set(links)].map((link) => link.match(re)[1]);
43+
const linkedHtmls = [...new Set(links)].map((link) => link.match(re)[1])
44+
.concat(['index.html']);
4445
const expectedJsons = linkedHtmls
4546
.map((name) => name.replace('.html', '.json'));
4647
const expectedDocs = linkedHtmls.concat(expectedJsons);

tools/doc/html.mjs

+65-15
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,10 @@ export function toHTML({ input, content, filename, nodeVersion, versions }) {
9898
.replace(/__FILENAME__/g, filename)
9999
.replace('__SECTION__', content.section)
100100
.replace(/__VERSION__/g, nodeVersion)
101-
.replace('__TOC__', content.toc)
102-
.replace('__GTOC__', gtocHTML.replace(
101+
.replace(/__TOC__/g, content.toc)
102+
.replace(/__TOC_PICKER__/g, tocPicker(id, content))
103+
.replace(/__GTOC_PICKER__/g, gtocPicker(id))
104+
.replace(/__GTOC__/g, gtocHTML.replace(
103105
`class="nav-${id}"`, `class="nav-${id} active"`))
104106
.replace('__EDIT_ON_GITHUB__', editOnGitHub(filename))
105107
.replace('__CONTENT__', processContent(content));
@@ -442,17 +444,18 @@ export function buildToc({ filename, apilinks }) {
442444
});
443445

444446
if (toc !== '') {
445-
file.toc = '<details id="toc" open><summary>Table of contents</summary>' +
446-
unified()
447-
.use(markdown)
448-
.use(gfm)
449-
.use(remark2rehype, { allowDangerousHtml: true })
450-
.use(raw)
451-
.use(htmlStringify)
452-
.processSync(toc).toString() +
453-
'</details>';
447+
const inner = unified()
448+
.use(markdown)
449+
.use(gfm)
450+
.use(remark2rehype, { allowDangerousHtml: true })
451+
.use(raw)
452+
.use(htmlStringify)
453+
.processSync(toc).toString();
454+
455+
file.toc = `<details id="toc" open><summary>Table of contents</summary>${inner}</details>`;
456+
file.tocPicker = `<div class="toc">${inner}</div>`;
454457
} else {
455-
file.toc = '<!-- TOC -->';
458+
file.toc = file.tocPicker = '<!-- TOC -->';
456459
}
457460
};
458461
}
@@ -508,13 +511,60 @@ function altDocs(filename, docCreated, versions) {
508511
const list = versions.filter(isDocInVersion).map(wrapInListItem).join('\n');
509512

510513
return list ? `
511-
<li class="version-picker">
512-
<a href="#">View another version <span>&#x25bc;</span></a>
513-
<ol class="version-picker">${list}</ol>
514+
<li class="picker-header">
515+
<a href="#">
516+
<span class="collapsed-arrow">&#x25ba;</span><span class="expanded-arrow">&#x25bc;</span>
517+
Other versions
518+
</a>
519+
<div class="picker"><ol id="alt-docs">${list}</ol></div>
514520
</li>
515521
` : '';
516522
}
517523

518524
function editOnGitHub(filename) {
519525
return `<li class="edit_on_github"><a href="https://github.com/nodejs/node/edit/master/doc/api/${filename}.md">Edit on GitHub</a></li>`;
520526
}
527+
528+
function gtocPicker(id) {
529+
if (id === 'index') {
530+
return '';
531+
}
532+
533+
// Highlight the current module and add a link to the index
534+
const gtoc = gtocHTML.replace(
535+
`class="nav-${id}"`, `class="nav-${id} active"`
536+
).replace('</ul>', `
537+
<li>
538+
<a href="index.html">Index</a>
539+
</li>
540+
</ul>
541+
`);
542+
543+
return `
544+
<li class="picker-header">
545+
<a href="#">
546+
<span class="collapsed-arrow">&#x25ba;</span><span class="expanded-arrow">&#x25bc;</span>
547+
Index
548+
</a>
549+
550+
<div class="picker">${gtoc}</div>
551+
</li>
552+
`;
553+
}
554+
555+
function tocPicker(id, content) {
556+
if (id === 'index') {
557+
return '';
558+
}
559+
560+
return `
561+
<li class="picker-header">
562+
<a href="#">
563+
<span class="collapsed-arrow">&#x25ba;</span><span class="expanded-arrow">&#x25bc;</span>
564+
Table of contents
565+
</a>
566+
567+
<div class="picker">${content.tocPicker}</div>
568+
</li>
569+
`;
570+
}

0 commit comments

Comments
 (0)