Skip to content

Commit

Permalink
doc,tools: improve navigability of API docs
Browse files Browse the repository at this point in the history
PR-URL: #41404
Reviewed-By: Rich Trott <[email protected]>
Reviewed-By: Antoine du Hamel <[email protected]>
  • Loading branch information
ShogunPanda authored and danielleadams committed Apr 24, 2022
1 parent a867867 commit 8c8dfa4
Show file tree
Hide file tree
Showing 4 changed files with 205 additions and 40 deletions.
130 changes: 117 additions & 13 deletions doc/api_assets/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ em code {
margin-bottom: 1rem;
}

#gtoc ul {
#gtoc > ul {
list-style: none;
margin-left: 0;
line-height: 1.5rem;
Expand All @@ -172,60 +172,106 @@ em code {
color: var(--color-critical);
}

li.version-picker {
li.picker-header {
position: relative;
}

li.version-picker:hover > a {
li.picker-header .collapsed-arrow, li.picker-header .expanded-arrow {
width: 1.5ch;
height: 1.5em;
}

li.picker-header .collapsed-arrow {
display: inline-block;
}

li.picker-header .expanded-arrow {
display: none;
}

li.picker-header:hover .collapsed-arrow {
display: none;
}

li.picker-header:hover .expanded-arrow {
display: inline-block;
}

li.picker-header:hover > a {
border-radius: 2px 2px 0 0;
}

li.version-picker:hover > ol {
li.picker-header:hover > .picker {
display: block;
z-index: 1;
}

li.version-picker a span {
li.picker-header a span {
font-size: .7rem;
}

ol.version-picker {
.picker {
background-color: var(--color-fill-app);
border: 1px solid var(--color-brand-secondary);
border-radius: 0 0 2px 2px;
display: none;
list-style: none;
position: absolute;
right: 0;
left: 0;
top: 100%;
width: 100%;
width: max-content;
min-width: min(300px, 75vw);
max-width: 75vw;
max-height: min(600px, 60vh);
overflow-y: auto;
}

#gtoc ol.version-picker li {
.picker > ul, .picker > ol {
list-style: none;
margin-left: 0;
line-height: 1.5rem;
}

.picker li {
display: block;
border-right: 0;
margin-right: 0;
}

ol.version-picker li a {
.picker li a {
border-radius: 0;
display: block;
margin: 0;
padding: .1rem;
padding-left: 1rem;
}

ol.version-picker li:last-child a {
.picker li a.active,
.picker li a.active:hover,
.picker li a.active:focus {
font-weight: 700;
}

.picker li:last-child a {
border-bottom-right-radius: 1px;
border-bottom-left-radius: 1px;
}

.gtoc-picker-header {
display: none;
}

.line {
width: calc(100% - 1rem);
display: block;
padding-bottom: 1px;
}

.picker .line {
margin: 0;
width: 100%;
}

.api_stability {
color: var(--white) !important;
margin: 0 0 1rem;
Expand Down Expand Up @@ -506,6 +552,41 @@ hr {
margin-top: .666rem;
}

.toc ul {
margin: 0
}

.toc li a::before {
content: "■";
color: var(--color-text-primary);
padding-right: 1em;
font-size: 0.9em;
}

.toc li a:hover::before {
color: var(--white);
}

.toc ul ul a {
padding-left: 1rem;
}

.toc ul ul ul a {
padding-left: 2rem;
}

.toc ul ul ul ul a {
padding-left: 3rem;
}

.toc ul ul ul ul ul a {
padding-left: 4rem;
}

.toc ul ul ul ul ul ul a {
padding-left: 5rem;
}

#toc .stability_0::after {
background-color: var(--red2);
color: var(--white);
Expand Down Expand Up @@ -718,10 +799,25 @@ kbd {
}
}

.header {
position: sticky;
top: -1px;
z-index: 1;
padding-top: 1rem;
background-color: var(--color-fill-app);
}

@media not screen, (max-height: 1000px) {
.header {
position: relative;
top: 0;
}
}

.header-container {
display: flex;
align-items: center;
margin: 1.5rem 0 1rem;
margin-bottom: 1rem;
justify-content: space-between;
}

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

@media only screen and (min-width: 577px) {
@media only screen and (min-width: 601px) {
#gtoc > ul > li {
display: inline;
border-right: 1px currentColor solid;
Expand All @@ -748,6 +844,10 @@ kbd {
margin-right: 0;
padding-right: 0;
}

#gtoc > ul > li.gtoc-picker-header {
display: none;
}
}

@media only screen and (max-width: 1024px) {
Expand All @@ -764,6 +864,10 @@ kbd {
#column2 {
display: none;
}

#gtoc > ul > li.gtoc-picker-header {
display: inline;
}
}

.icon {
Expand Down
32 changes: 21 additions & 11 deletions doc/template.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
</div>

<div id="column1" data-id="__ID__" class="interior">
<header>
<header class="header">
<div class="header-container">
<h1>Node.js __VERSION__ documentation</h1>
<button class="theme-toggle-btn" id="theme-toggle-btn" title="Toggle dark mode/light mode" aria-label="Toggle dark mode/light mode" hidden>
Expand All @@ -39,17 +39,27 @@ <h1>Node.js __VERSION__ documentation</h1>
</div>
<div id="gtoc">
<ul>
<li>
<a href="index.html">Index</a>
</li>
<li>
<a href="all.html">View on single page</a>
</li>
<li>
<a href="__FILENAME__.json">View as JSON</a>
</li>
__TOC_PICKER__
__GTOC_PICKER__
__ALTDOCS__
__EDIT_ON_GITHUB__
<li class="picker-header">
<a href="#">
<span class="collapsed-arrow">&#x25ba;</span><span class="expanded-arrow">&#x25bc;</span>
Options
</a>

<div class="picker">
<ul>
<li>
<a href="all.html">View on single page</a>
</li>
<li>
<a href="__FILENAME__.json">View as JSON</a>
</li>
__EDIT_ON_GITHUB__
</ul>
</div>
</li>
</ul>
</div>
<hr>
Expand Down
3 changes: 2 additions & 1 deletion test/doctool/test-make-doc.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ const links = toc.match(globalRe);
assert.notStrictEqual(links, null);

// Filter out duplicate links, leave just filenames, add expected JSON files.
const linkedHtmls = [...new Set(links)].map((link) => link.match(re)[1]);
const linkedHtmls = [...new Set(links)].map((link) => link.match(re)[1])
.concat(['index.html']);
const expectedJsons = linkedHtmls
.map((name) => name.replace('.html', '.json'));
const expectedDocs = linkedHtmls.concat(expectedJsons);
Expand Down
80 changes: 65 additions & 15 deletions tools/doc/html.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,10 @@ export function toHTML({ input, content, filename, nodeVersion, versions }) {
.replace(/__FILENAME__/g, filename)
.replace('__SECTION__', content.section)
.replace(/__VERSION__/g, nodeVersion)
.replace('__TOC__', content.toc)
.replace('__GTOC__', gtocHTML.replace(
.replace(/__TOC__/g, content.toc)
.replace(/__TOC_PICKER__/g, tocPicker(id, content))
.replace(/__GTOC_PICKER__/g, gtocPicker(id))
.replace(/__GTOC__/g, gtocHTML.replace(
`class="nav-${id}"`, `class="nav-${id} active"`))
.replace('__EDIT_ON_GITHUB__', editOnGitHub(filename))
.replace('__CONTENT__', processContent(content));
Expand Down Expand Up @@ -442,17 +444,18 @@ export function buildToc({ filename, apilinks }) {
});

if (toc !== '') {
file.toc = '<details id="toc" open><summary>Table of contents</summary>' +
unified()
.use(markdown)
.use(gfm)
.use(remark2rehype, { allowDangerousHtml: true })
.use(raw)
.use(htmlStringify)
.processSync(toc).toString() +
'</details>';
const inner = unified()
.use(markdown)
.use(gfm)
.use(remark2rehype, { allowDangerousHtml: true })
.use(raw)
.use(htmlStringify)
.processSync(toc).toString();

file.toc = `<details id="toc" open><summary>Table of contents</summary>${inner}</details>`;
file.tocPicker = `<div class="toc">${inner}</div>`;
} else {
file.toc = '<!-- TOC -->';
file.toc = file.tocPicker = '<!-- TOC -->';
}
};
}
Expand Down Expand Up @@ -508,13 +511,60 @@ function altDocs(filename, docCreated, versions) {
const list = versions.filter(isDocInVersion).map(wrapInListItem).join('\n');

return list ? `
<li class="version-picker">
<a href="#">View another version <span>&#x25bc;</span></a>
<ol class="version-picker">${list}</ol>
<li class="picker-header">
<a href="#">
<span class="collapsed-arrow">&#x25ba;</span><span class="expanded-arrow">&#x25bc;</span>
Other versions
</a>
<div class="picker"><ol id="alt-docs">${list}</ol></div>
</li>
` : '';
}

function editOnGitHub(filename) {
return `<li class="edit_on_github"><a href="https://github.com/nodejs/node/edit/master/doc/api/${filename}.md">Edit on GitHub</a></li>`;
}

function gtocPicker(id) {
if (id === 'index') {
return '';
}

// Highlight the current module and add a link to the index
const gtoc = gtocHTML.replace(
`class="nav-${id}"`, `class="nav-${id} active"`
).replace('</ul>', `
<li>
<a href="index.html">Index</a>
</li>
</ul>
`);

return `
<li class="picker-header">
<a href="#">
<span class="collapsed-arrow">&#x25ba;</span><span class="expanded-arrow">&#x25bc;</span>
Index
</a>
<div class="picker">${gtoc}</div>
</li>
`;
}

function tocPicker(id, content) {
if (id === 'index') {
return '';
}

return `
<li class="picker-header">
<a href="#">
<span class="collapsed-arrow">&#x25ba;</span><span class="expanded-arrow">&#x25bc;</span>
Table of contents
</a>
<div class="picker">${content.tocPicker}</div>
</li>
`;
}

0 comments on commit 8c8dfa4

Please sign in to comment.