diff --git a/docs/dockhand.js b/docs/dockhand.js
index 41d01b1cff685..b66ec609d4fde 100644
--- a/docs/dockhand.js
+++ b/docs/dockhand.js
@@ -1,227 +1,218 @@
#!/usr/bin/env node
-const path = require('path');
-const fs = require('fs');
-const yaml = require('yaml');
-const cmark = require('cmark-gfm');
-const mkdirp = require('mkdirp');
-const jsdom = require('jsdom');
+const path = require('path')
+const fs = require('fs')
+const yaml = require('yaml')
+const cmark = require('cmark-gfm')
+const mkdirp = require('mkdirp')
+const jsdom = require('jsdom')
const npm = require('../lib/npm.js')
-const config = require('./config.json');
+const config = require('./config.json')
-const docsRoot = __dirname;
-const inputRoot = path.join(docsRoot, 'content');
-const outputRoot = path.join(docsRoot, 'output');
+const docsRoot = __dirname
+const inputRoot = path.join(docsRoot, 'content')
+const outputRoot = path.join(docsRoot, 'output')
-const template = fs.readFileSync('template.html').toString();
+const template = fs.readFileSync('template.html').toString()
-walk(inputRoot);
+walk(inputRoot)
-function walk(root, dirRelative) {
- const dirPath = dirRelative ? path.join(root, dirRelative) : root;
+function walk (root, dirRelative) {
+ const dirPath = dirRelative ? path.join(root, dirRelative) : root
- fs.readdirSync(dirPath).forEach((childFilename) => {
- const childRelative = dirRelative ? path.join(dirRelative, childFilename) : childFilename;
- const childPath = path.join(root, childRelative);
+ fs.readdirSync(dirPath).forEach((childFilename) => {
+ const childRelative = dirRelative ? path.join(dirRelative, childFilename) : childFilename
+ const childPath = path.join(root, childRelative)
- if (fs.lstatSync(childPath).isDirectory()) {
- walk(root, childRelative);
- }
- else {
- translate(childRelative);
- }
- });
+ if (fs.lstatSync(childPath).isDirectory()) {
+ walk(root, childRelative)
+ } else {
+ translate(childRelative)
+ }
+ })
}
-function translate(childPath) {
- const inputPath = path.join(inputRoot, childPath);
-
- if (!inputPath.match(/\.md$/)) {
- console.log(`warning: unknown file type ${inputPath}, ignored`);
- return;
+function translate (childPath) {
+ const inputPath = path.join(inputRoot, childPath)
+
+ if (!inputPath.match(/\.md$/)) {
+ console.log(`warning: unknown file type ${inputPath}, ignored`)
+ return
+ }
+
+ const outputPath = path.join(outputRoot, childPath.replace(/\.md$/, '.html'))
+
+ let md = fs.readFileSync(inputPath).toString()
+ let frontmatter = { }
+
+ // Take the leading frontmatter out of the markdown
+ md = md.replace(/^---\n([\s\S]+)\n---\n/, (header, fm) => {
+ frontmatter = yaml.parse(fm, 'utf8')
+ return ''
+ })
+
+ // Replace any tokens in the source
+ md = md.replace(/@VERSION@/, npm.version)
+
+ // Render the markdown into an HTML snippet using a GFM renderer.
+ const content = cmark.renderHtmlSync(md, {
+ 'smart': true,
+ 'githubPreLang': true,
+ 'strikethroughDoubleTilde': true,
+ 'unsafe': false,
+ extensions: {
+ 'table': true,
+ 'strikethrough': true,
+ 'tagfilter': true,
+ 'autolink': true
}
+ })
+
+ // Inject this data into the template, using a mustache-like
+ // replacement scheme.
+ const html = template.replace(/\{\{\s*([\w.]+)\s*\}\}/g, (token, key) => {
+ switch (key) {
+ case 'content':
+ return `
${content}
`
+ case 'path':
+ return childPath
+ case 'url_path':
+ return encodeURI(childPath)
+
+ case 'toc':
+ return ''
+
+ case 'title':
+ case 'section':
+ case 'description':
+ return frontmatter[key]
+
+ case 'config.github_repo':
+ case 'config.github_branch':
+ case 'config.github_path':
+ return config[key.replace(/^config\./, '')]
+
+ default:
+ console.log(`warning: unknown token '${token}' in ${inputPath}`)
+ return ''
+ }
+ })
- const outputPath = path.join(outputRoot, childPath.replace(/\.md$/, '.html'));
-
- let md = fs.readFileSync(inputPath).toString();
- let frontmatter = { };
-
- // Take the leading frontmatter out of the markdown
- md = md.replace(/^---\n([\s\S]+)\n---\n/, (header, fm) => {
- frontmatter = yaml.parse(fm, 'utf8');
- return '';
- });
-
- // Replace any tokens in the source
- md = md.replace(/@VERSION@/, npm.version);
-
- // Render the markdown into an HTML snippet using a GFM renderer.
- const content = cmark.renderHtmlSync(md, {
- 'smart': true,
- 'githubPreLang': true,
- 'strikethroughDoubleTilde': true,
- 'unsafe': false,
- extensions: {
- 'table': true,
- 'strikethrough': true,
- 'tagfilter': true,
- 'autolink': true
- }
- });
-
- // Inject this data into the template, using a mustache-like
- // replacement scheme.
- const html = template.replace(/\{\{\s*([\w\.]+)\s*\}\}/g, (token, key) => {
- switch (key) {
- case 'content':
- return `${content}
`;
- case 'path':
- return childPath;
- case 'url_path':
- return encodeURI(childPath);
-
- case 'toc':
- return '';
-
- case 'title':
- case 'section':
- case 'description':
- return frontmatter[key];
-
- case 'config.github_repo':
- case 'config.github_branch':
- case 'config.github_path':
- return config[key.replace(/^config\./, '')];
-
- default:
- console.log(`warning: unknown token '${token}' in ${inputPath}`);
- return '';
- }
- console.log(key);
- return key;
- });
-
- const dom = new jsdom.JSDOM(html);
- const document = dom.window.document;
-
- // Rewrite relative URLs in links and image sources to be relative to
- // this file; this is for supporting `file://` links. HTML pages need
- // suffix appended.
- const links = [
- { tag: 'a', attr: 'href', suffix: '.html' },
- { tag: 'img', attr: 'src' }
- ];
-
- for (let linktype of links) {
- for (let tag of document.querySelectorAll(linktype.tag)) {
- let url = tag.getAttribute(linktype.attr);
+ const dom = new jsdom.JSDOM(html)
+ const document = dom.window.document
- if (url.startsWith('/')) {
- const childDepth = childPath.split('/').length - 1;
- const prefix = childDepth > 0 ? '../'.repeat(childDepth) : './';
+ // Rewrite relative URLs in links and image sources to be relative to
+ // this file; this is for supporting `file://` links. HTML pages need
+ // suffix appended.
+ const links = [
+ { tag: 'a', attr: 'href', suffix: '.html' },
+ { tag: 'img', attr: 'src' }
+ ]
- url = url.replace(/^\//, prefix);
+ for (let linktype of links) {
+ for (let tag of document.querySelectorAll(linktype.tag)) {
+ let url = tag.getAttribute(linktype.attr)
- if (linktype.suffix) {
- url += linktype.suffix;
- }
+ if (url.startsWith('/')) {
+ const childDepth = childPath.split('/').length - 1
+ const prefix = childDepth > 0 ? '../'.repeat(childDepth) : './'
- tag.setAttribute(linktype.attr, url);
- }
- }
- }
+ url = url.replace(/^\//, prefix)
- // Give headers a unique id so that they can be linked within the doc
- const headerIds = [ ];
- for (let header of document.querySelectorAll('h1, h2, h3, h4, h5, h6')) {
- if (header.getAttribute('id')) {
- headerIds.push(header.getAttribute('id'));
- continue;
+ if (linktype.suffix) {
+ url += linktype.suffix
}
- const headerText = header.textContent.replace(/[A-Z]/g, x => x.toLowerCase()).replace(/ /g, '-').replace(/[^a-z0-9\-]/g, '');
- let headerId = headerText;
- let headerIncrement = 1;
+ tag.setAttribute(linktype.attr, url)
+ }
+ }
+ }
+
+ // Give headers a unique id so that they can be linked within the doc
+ const headerIds = [ ]
+ for (let header of document.querySelectorAll('h1, h2, h3, h4, h5, h6')) {
+ if (header.getAttribute('id')) {
+ headerIds.push(header.getAttribute('id'))
+ continue
+ }
- while (document.getElementById(headerId) !== null) {
- headerId = headerText + (++headerIncrement);
- }
+ const headerText = header.textContent.replace(/[A-Z]/g, x => x.toLowerCase()).replace(/ /g, '-').replace(/[^a-z0-9-]/g, '')
+ let headerId = headerText
+ let headerIncrement = 1
- headerIds.push(headerId);
- header.setAttribute('id', headerId);
+ while (document.getElementById(headerId) !== null) {
+ headerId = headerText + (++headerIncrement)
}
- // Walk the dom and build a table of contents
- const toc = document.getElementById('_table_of_contents');
+ headerIds.push(headerId)
+ header.setAttribute('id', headerId)
+ }
- if (toc) {
- toc.appendChild(generateTableOfContents(document));
- }
+ // Walk the dom and build a table of contents
+ const toc = document.getElementById('_table_of_contents')
- // Write the final output
- const output = dom.serialize();
+ if (toc) {
+ toc.appendChild(generateTableOfContents(document))
+ }
- mkdirp.sync(path.dirname(outputPath));
- fs.writeFileSync(outputPath, output);
-}
+ // Write the final output
+ const output = dom.serialize()
-function generateTableOfContents(document) {
- const headers = [ ];
- walkHeaders(document.getElementById('_content'), headers);
+ mkdirp.sync(path.dirname(outputPath))
+ fs.writeFileSync(outputPath, output)
+}
- let parent = null;
+function generateTableOfContents (document) {
+ const headers = [ ]
+ walkHeaders(document.getElementById('_content'), headers)
- // The nesting depth of headers are not necessarily the header level.
- // (eg, h1 > h3 > h5 is a depth of three even though there's an h5.)
- const hierarchy = [ ];
- for (let header of headers) {
- const level = headerLevel(header);
+ // The nesting depth of headers are not necessarily the header level.
+ // (eg, h1 > h3 > h5 is a depth of three even though there's an h5.)
+ const hierarchy = [ ]
+ for (let header of headers) {
+ const level = headerLevel(header)
- while (hierarchy.length && hierarchy[hierarchy.length - 1].headerLevel > level) {
- hierarchy.pop();
- }
+ while (hierarchy.length && hierarchy[hierarchy.length - 1].headerLevel > level) {
+ hierarchy.pop()
+ }
- if (!hierarchy.length || hierarchy[hierarchy.length - 1].headerLevel < level) {
- const newList = document.createElement('ul');
- newList.headerLevel = level;
+ if (!hierarchy.length || hierarchy[hierarchy.length - 1].headerLevel < level) {
+ const newList = document.createElement('ul')
+ newList.headerLevel = level
- if (hierarchy.length) {
- hierarchy[hierarchy.length - 1].appendChild(newList);
- }
+ if (hierarchy.length) {
+ hierarchy[hierarchy.length - 1].appendChild(newList)
+ }
- hierarchy.push(newList);
- }
+ hierarchy.push(newList)
+ }
- const element = document.createElement('li');
+ const element = document.createElement('li')
- const link = document.createElement('a');
- link.setAttribute('href', `#${header.getAttribute('id')}`);
- link.innerHTML = header.innerHTML;
- element.appendChild(link);
+ const link = document.createElement('a')
+ link.setAttribute('href', `#${header.getAttribute('id')}`)
+ link.innerHTML = header.innerHTML
+ element.appendChild(link)
- const list = hierarchy[hierarchy.length - 1];
- list.appendChild(element);
- }
+ const list = hierarchy[hierarchy.length - 1]
+ list.appendChild(element)
+ }
- return hierarchy[0];
+ return hierarchy[0]
}
-function walkHeaders(element, headers) {
- for (let child of element.childNodes) {
- if (headerLevel(child)) {
- headers.push(child);
- }
-
- walkHeaders(child, headers);
+function walkHeaders (element, headers) {
+ for (let child of element.childNodes) {
+ if (headerLevel(child)) {
+ headers.push(child)
}
-}
-function headerLevel(node) {
- const level = node.tagName ? node.tagName.match(/^[Hh]([123456])$/) : null;
- return level ? level[1] : 0;
+ walkHeaders(child, headers)
+ }
}
-function debug(str) {
- console.log(str);
+function headerLevel (node) {
+ const level = node.tagName ? node.tagName.match(/^[Hh]([123456])$/) : null
+ return level ? level[1] : 0
}