Skip to content
Browse files

chore(docs): add navigation configuration

The documentation in this repository is added to the overall npm
documentation at, which includes both the
documentation for the public registry and the CLI.

The documentation site itself also has a navigational hierarchy;
since the content is included from the CLI, we also want to ensure
that the navigation for that content lives in this repository.

This means that this repository is the source of truth for all of the
CLI documentation, and we do not need to update two places when we
add, edit, or remove CLI documentation.  It all lives here.

This also teaches the documentation rendering script to identify when
the navigation configuration (nav.yml) is missing new pages that were
recently added or retains old pages that have recently been deleted.

PR-URL: #2775
Credit: @ethomson
Close: #2775
Reviewed-by: @wraithgar
  • Loading branch information
ethomson authored and wraithgar committed Feb 25, 2021
1 parent b7e37f6 commit e45242ca0275ab4938723faed8e7391e1209e996
Showing with 341 additions and 6 deletions.
  1. +1 −0 .npmignore
  2. +91 −6 docs/dockhand.js
  3. +249 −0 docs/nav.yml
@@ -16,6 +16,7 @@ node_modules/npm-registry-mock

# don't need these in the npm package.

# don't ignore .npmignore files
# these are used in some tests.
@@ -19,7 +19,12 @@ const template = fs.readFileSync('template.html').toString();

const run = async function() {
try {
await walk(inputRoot);
const navPaths = await getNavigationPaths();
const fsPaths = await renderFilesystemPaths();

if (!ensureNavigationComplete(navPaths, fsPaths)) {
catch (error) {
@@ -28,7 +33,85 @@ const run = async function() {


async function walk(root, dirRelative) {
function ensureNavigationComplete(navPaths, fsPaths) {
const unmatchedNav = { }, unmatchedFs = { };

for (const navPath of navPaths) {
unmatchedNav[navPath] = true;

for (let fsPath of fsPaths) {
fsPath = '/' + fsPath.replace(/\.md$/, "");

if (unmatchedNav[fsPath]) {
delete unmatchedNav[fsPath];
else {
unmatchedFs[fsPath] = true;

const missingNav = Object.keys(unmatchedNav).sort();
const missingFs = Object.keys(unmatchedFs).sort()

if (missingNav.length > 0 || missingFs.length > 0) {
let message = "Error: documentation navigation (nav.yml) does not match filesystem.\n";

if (missingNav.length > 0) {
message += "\nThe following path(s) exist on disk but are not present in nav.yml:\n\n";

for (const nav of missingNav) {
message += ` ${nav}\n`;

if (missingNav.length > 0 && missingFs.length > 0) {
message += "\nThe following path(s) exist in nav.yml but are not present on disk:\n\n";

for (const fs of missingFs) {
message += ` ${fs}\n`;

message += "\nUpdate nav.yml to ensure that all files are listed in the appropriate place.";


return false;

return true;

function getNavigationPaths() {
const navFilename = path.join(docsRoot, 'nav.yml');
const nav = yaml.parse(fs.readFileSync(navFilename).toString(), 'utf8');

return walkNavigation(nav);

function walkNavigation(entries) {
const paths = [ ]

for (const entry of entries) {
if (entry.children) {
paths.push(... walkNavigation(entry.children));
else {

return paths;

async function renderFilesystemPaths() {
return await walkFilesystem(inputRoot);

async function walkFilesystem(root, dirRelative) {
const paths = [ ]

const dirPath = dirRelative ? path.join(root, dirRelative) : root;
const children = fs.readdirSync(dirPath);

@@ -37,15 +120,18 @@ async function walk(root, dirRelative) {
const childPath = path.join(root, childRelative);

if (fs.lstatSync(childPath).isDirectory()) {
await walk(root, childRelative);
paths.push(... await walkFilesystem(root, childRelative));
else {
await translate(childRelative);
await renderFile(childRelative);

return paths;

async function translate(childPath) {
async function renderFile(childPath) {
const inputPath = path.join(inputRoot, childPath);

if (!inputPath.match(/\.md$/)) {
@@ -119,7 +205,6 @@ async function translate(childPath) {
console.log(`warning: unknown token '${token}' in ${inputPath}`);
return '';
return key;

@@ -0,0 +1,249 @@
# This is the navigation for the documentation pages; it is not used
# directly within the CLI documentation. Instead, it will be used
# for the site.

- title: CLI Commands
shortName: Commands
url: /commands
- title: npm
url: /commands/npm
description: JavaScript package manager
- title: npm access
url: /commands/npm-access
description: Set access level on published packages
- title: npm adduser
url: /commands/npm-adduser
description: Add a registry user account
- title: npm audit
url: /commands/npm-audit
description: Run a security audit
- title: npm bin
url: /commands/npm-bin
description: Display npm bin folder
- title: npm bugs
url: /commands/npm-bugs
description: Bugs for a package in a web browser maybe
- title: npm cache
url: /commands/npm-cache
description: Manipulates packages cache
- title: npm ci
url: /commands/npm-ci
description: Install a project with a clean slate
- title: npm completion
url: /commands/npm-completion
description: Tab completion for npm
- title: npm config
url: /commands/npm-config
description: Manage the npm configuration files
- title: npm dedupe
url: /commands/npm-dedupe
description: Reduce duplication
- title: npm deprecate
url: /commands/npm-deprecate
description: Deprecate a version of a package
- title: npm diff
url: /commands/npm-diff
description: The registry diff command
- title: npm dist-tag
url: /commands/npm-dist-tag
description: Modify package distribution tags
- title: npm docs
url: /commands/npm-docs
description: Docs for a package in a web browser maybe
- title: npm doctor
url: /commands/npm-doctor
description: Check your environments
- title: npm edit
url: /commands/npm-edit
description: Edit an installed package
- title: npm exec
url: /commands/npm-exec
description: Run a command from an npm package
- title: npm explain
url: /commands/npm-explain
description: Explain installed packages
- title: npm explore
url: /commands/npm-explore
description: Browse an installed package
- title: npm fund
url: /commands/npm-fund
description: Retrieve funding information
- title: npm help
url: /commands/npm-help
description: Search npm help documentation
- title: npm help-search
url: /commands/npm-help-search
description: Get help on npm
- title: npm hook
url: /commands/npm-hook
description: Manage registry hooks
- title: npm init
url: /commands/npm-init
description: Create a package.json file
- title: npm install
url: /commands/npm-install
description: Install a package
- title: npm install-ci-test
url: /commands/npm-install-ci-test
description: Install a project with a clean slate and run tests
- title: npm install-test
url: /commands/npm-install-test
description: Install package(s) and run tests
- title: npm link
url: /commands/npm-link
description: Symlink a package folder
- title: npm logout
url: /commands/npm-logout
description: Log out of the registry
- title: npm ls
url: /commands/npm-ls
description: List installed packages
- title: npm org
url: /commands/npm-org
description: Manage orgs
- title: npm outdated
url: /commands/npm-outdated
description: Check for outdated packages
- title: npm owner
url: /commands/npm-owner
description: Manage package owners
- title: npm pack
url: /commands/npm-pack
description: Create a tarball from a package
- title: npm ping
url: /commands/npm-ping
description: Ping npm registry
- title: npm prefix
url: /commands/npm-prefix
description: Display prefix
- title: npm profile
url: /commands/npm-profile
description: Change settings on your registry profile
- title: npm prune
url: /commands/npm-prune
description: Remove extraneous packages
- title: npm publish
url: /commands/npm-publish
description: Publish a package
- title: npm rebuild
url: /commands/npm-rebuild
description: Rebuild a package
- title: npm repo
url: /commands/npm-repo
description: Open package repository page in the browser
- title: npm restart
url: /commands/npm-restart
description: Restart a package
- title: npm root
url: /commands/npm-root
description: Display npm root
- title: npm run-script
url: /commands/npm-run-script
description: Run arbitrary package scripts
- title: npm search
url: /commands/npm-search
description: Search for packages
- title: npm set-script
url: /commands/npm-set-script
description: Set tasks in the scripts section of package.json
- title: npm shrinkwrap
url: /commands/npm-shrinkwrap
description: Lock down dependency versions for publication
- title: npm star
url: /commands/npm-star
description: Mark your favorite packages
- title: npm stars
url: /commands/npm-stars
description: View packages marked as favorites
- title: npm start
url: /commands/npm-start
description: Start a package
- title: npm stop
url: /commands/npm-stop
description: Stop a package
- title: npm team
url: /commands/npm-team
description: Manage organization teams and team memberships
- title: npm test
url: /commands/npm-test
description: Test a package
- title: npm token
url: /commands/npm-token
description: Manage your authentication tokens
- title: npm uninstall
url: /commands/npm-uninstall
description: Remove a package
- title: npm unpublish
url: /commands/npm-unpublish
description: Remove a package from the registry
- title: npm unstar
url: /commands/npm-unstar
description: Remove an item from your favorite packages
- title: npm update
url: /commands/npm-update
description: Update a package
- title: npm version
url: /commands/npm-version
description: Bump a package version
- title: npm view
url: /commands/npm-view
description: View registry info
- title: npm whoami
url: /commands/npm-whoami
description: Display npm username
- title: npx
url: /commands/npx
description: Run a command from an npm package

- title: Configuring npm
shortName: Configuring
url: /configuring-npm
- title: Install
url: /configuring-npm/install
description: Download and install node and npm
- title: Folders
url: /configuring-npm/folders
description: Folder structures used by npm
- title: .npmrc
url: /configuring-npm/npmrc
description: The npm config files
- title: npm-shrinkwrap.json
url: /configuring-npm/npm-shrinkwrap-json
description: A publishable lockfile
- title: package.json
url: /configuring-npm/package-json
description: Specifics of npm's package.json handling
- title: package-lock.json
url: /configuring-npm/package-lock-json
description: A manifestation of the manifest

- title: Using npm
shortName: Using
url: /using-npm
- title: Registry
url: /using-npm/registry
description: The JavaScript Package Registry
- title: Config
url: /using-npm/config
description: About npm configuration
- title: Scope
url: /using-npm/scope
description: Scoped packages
- title: Scripts
url: /using-npm/scripts
description: How npm handles the "scripts" field
- title: Workspaces
url: /using-npm/workspaces
description: Working with workspaces
- title: Organizations
url: /using-npm/orgs
description: Working with teams & organizations
- title: Developers
url: /using-npm/developers
description: Developer guide
- title: Removal
url: /using-npm/removal
description: Cleaning the slate

0 comments on commit e45242c

Please sign in to comment.