Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
doc,tools: use only one level 1 header per page
Increment the header levels from markdown files when producing HTML
documents. This is both better semantically (as the two h1 headers in
current docs are not actually equivalent level semantically--the second
belongs below/inside the first) and better for accessibility. (It is
valid HTML to have multiple h1 headers in a document, but it can be bad
for screen reader experience.)

PR-URL: #37839
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Pooja D P <Pooja.D.P@ibm.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
  • Loading branch information
Trott committed Mar 25, 2021
commit 3700ba0be3813db4567031f3464dd1370c0dd965
38 changes: 19 additions & 19 deletions test/doctool/test-doctool-html.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,25 +60,25 @@ function toHTML({ input, filename, nodeVersion, versions }) {
const testData = [
{
file: fixtures.path('order_of_end_tags_5873.md'),
html: '<h3>Static method: Buffer.from(array) <span> ' +
html: '<h4>Static method: Buffer.from(array) <span> ' +
'<a class="mark" href="#foo_static_method_buffer_from_array" ' +
'id="foo_static_method_buffer_from_array">#</a> </span> </h3>' +
'id="foo_static_method_buffer_from_array">#</a> </span> </h4>' +
'<ul><li><code>array</code><a ' +
'href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/' +
'Reference/Global_Objects/Array" class="type">&#x3C;Array></a></li></ul>'
},
{
file: fixtures.path('doc_with_yaml.md'),
html: '<h1>Sample Markdown with YAML info' +
html: '<h2>Sample Markdown with YAML info' +
'<span><a class="mark" href="#foo_sample_markdown_with_yaml_info" ' +
' id="foo_sample_markdown_with_yaml_info">#</a></span></h1>' +
'<section><h2>Foobar<span><a class="mark" href="#foo_foobar" ' +
'id="foo_foobar">#</a></span></h2>' +
' id="foo_sample_markdown_with_yaml_info">#</a></span></h2>' +
'<section><h3>Foobar<span><a class="mark" href="#foo_foobar" ' +
'id="foo_foobar">#</a></span></h3>' +
'<div class="api_metadata"><span>Added in: v1.0.0</span></div> ' +
'<p>Describe <code>Foobar</code> in more detail here.</p>' +
'</section><section>' +
'<h2>Foobar II<span><a class="mark" href="#foo_foobar_ii" ' +
'id="foo_foobar_ii">#</a></span></h2><div class="api_metadata">' +
'<h3>Foobar II<span><a class="mark" href="#foo_foobar_ii" ' +
'id="foo_foobar_ii">#</a></span></h3><div class="api_metadata">' +
'<details class="changelog"><summary>History</summary>' +
'<table><tbody><tr><th>Version</th><th>Changes</th></tr>' +
'<tr><td>v5.3.0, v4.2.0</td>' +
Expand All @@ -88,15 +88,15 @@ const testData = [
'<p>Describe <code>Foobar II</code> in more detail here.' +
'<a href="http://man7.org/linux/man-pages/man1/fg.1.html"><code>fg(1)' +
'</code></a></p></section><section>' +
'<h2>Deprecated thingy<span><a class="mark" ' +
'<h3>Deprecated thingy<span><a class="mark" ' +
'href="#foo_deprecated_thingy" id="foo_deprecated_thingy">#</a>' +
'</span></h2><div class="api_metadata"><span>Added in: v1.0.0</span>' +
'</span></h3><div class="api_metadata"><span>Added in: v1.0.0</span>' +
'<span>Deprecated since: v2.0.0</span></div><p>Describe ' +
'<code>Deprecated thingy</code> in more detail here.' +
'<a href="http://man7.org/linux/man-pages/man1/fg.1p.html"><code>fg(1p)' +
'</code></a></p></section><section>' +
'<h2>Something<span><a class="mark" href="#foo_something' +
'" id="foo_something">#</a></span></h2> ' +
'<h3>Something<span><a class="mark" href="#foo_something' +
'" id="foo_something">#</a></span></h3> ' +
'<!-- This is not a metadata comment --> ' +
'<p>Describe <code>Something</code> in more detail here. </p></section>'
},
Expand All @@ -111,19 +111,19 @@ const testData = [
},
{
file: fixtures.path('document_with_links.md'),
html: '<h1>Usage and Example<span><a class="mark"' +
html: '<h2>Usage and Example<span><a class="mark"' +
'href="#foo_usage_and_example" id="foo_usage_and_example">#</a>' +
'</span></h1><section><h2>Usage<span><a class="mark" href="#foo_usage"' +
'id="foo_usage">#</a></span></h2><p><code>node \\[options\\] index.js' +
'</span></h2><section><h3>Usage<span><a class="mark" href="#foo_usage"' +
'id="foo_usage">#</a></span></h3><p><code>node \\[options\\] index.js' +
'</code></p><p>Please see the<a href="cli.html#cli-options">' +
'Command Line Options</a>document for more information.</p>' +
'</section><section><h2>' +
'</section><section><h3>' +
'Example<span><a class="mark" href="#foo_example" id="foo_example">' +
'#</a></span></h2><p>An example of a<a href="example.html">' +
'#</a></span></h3><p>An example of a<a href="example.html">' +
'webserver</a>written with Node.js which responds with<code>' +
'\'Hello, World!\'</code>:</p></section><section>' +
'<h2>See also<span><a class="mark"' +
'href="#foo_see_also" id="foo_see_also">#</a></span></h2><p>Check' +
'<h3>See also<span><a class="mark"' +
'href="#foo_see_also" id="foo_see_also">#</a></span></h3><p>Check' +
'out also<a href="https://nodejs.org/">this guide</a></p></section>'
},
{
Expand Down
17 changes: 13 additions & 4 deletions tools/doc/html.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,19 @@ const gtocHTML = unified()
const templatePath = path.join(docPath, 'template.html');
const template = fs.readFileSync(templatePath, 'utf8');

function wrapSections(content) {
function processContent(content) {
content = content.toString();
// Increment header tag levels to avoid multiple h1 tags in a doc.
// This means we can't already have an <h6>.
if (content.includes('<h6>')) {
throw new Error('Cannot increment a level 6 header');
}
Comment thread
Trott marked this conversation as resolved.
Resolved
// `++level` to convert the string to a number and increment it.
content = content.replace(/(?<=<\/?h)[1-5](?=[^<>]*>)/g, (level) => ++level);
// Wrap h3 tags in section tags.
let firstTime = true;
return content.toString()
.replace(/<h2/g, (heading) => {
return content
.replace(/<h3/g, (heading) => {
if (firstTime) {
firstTime = false;
return '<section>' + heading;
Expand All @@ -91,7 +100,7 @@ function toHTML({ input, content, filename, nodeVersion, versions }) {
.replace('__GTOC__', gtocHTML.replace(
`class="nav-${id}"`, `class="nav-${id} active"`))
.replace('__EDIT_ON_GITHUB__', editOnGitHub(filename))
.replace('__CONTENT__', wrapSections(content));
.replace('__CONTENT__', processContent(content));

const docCreated = input.match(
/<!--\s*introduced_in\s*=\s*v([0-9]+)\.([0-9]+)\.[0-9]+\s*-->/);
Expand Down