Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/npm/cli.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorLuke Karrys <luke@lukekarrys.com>2022-03-31 03:39:21 +0300
committerGar <wraithgar@github.com>2022-04-06 19:26:45 +0300
commit03f36bf8c30b713e86f8e0b7e6643b68d74f7d91 (patch)
treeafc33df0328cfda57f8cb5e4a7126fc615f00281 /docs
parent840c338aa6aba7dc39d9d3afba075701e3979362 (diff)
chore(docs): move scripts and refactor
All docs related scripts are now located in the docs workspace
Diffstat (limited to 'docs')
-rw-r--r--docs/.gitignore1
-rw-r--r--docs/bin/config-doc-command.js142
-rw-r--r--docs/bin/config-doc.js63
-rw-r--r--docs/bin/dockhand.js65
-rw-r--r--docs/bin/docs-build.js39
-rw-r--r--docs/lib/config.json (renamed from docs/bin/config.json)0
-rw-r--r--docs/lib/npm.js14
-rw-r--r--docs/lib/template.html (renamed from docs/bin/template.html)0
-rw-r--r--docs/package.json6
-rw-r--r--docs/test/index.js8
10 files changed, 298 insertions, 40 deletions
diff --git a/docs/.gitignore b/docs/.gitignore
index 823857bf9..2231d46ac 100644
--- a/docs/.gitignore
+++ b/docs/.gitignore
@@ -18,5 +18,6 @@
!/.gitignore
!/bin/
!/content/
+!/lib/
!/nav.yml
!/package.json
diff --git a/docs/bin/config-doc-command.js b/docs/bin/config-doc-command.js
new file mode 100644
index 000000000..f55213cdc
--- /dev/null
+++ b/docs/bin/config-doc-command.js
@@ -0,0 +1,142 @@
+const fs = require('fs').promises
+const { resolve } = require('path')
+const { definitions, aliases } = require('../lib/npm.js')
+
+const describeAll = (content) =>
+ content.map(name => definitions[name].describe()).join(
+ '\n\n<!-- automatically generated, do not edit manually -->\n' +
+ '<!-- see lib/utils/config/definitions.js -->\n\n'
+ )
+
+const describeUsage = ({ usage, configDoc, commandFile }) => {
+ const synopsis = []
+
+ // Grab the command name from the *.md filename
+ // NOTE: We cannot use the name property command file because in the case of
+ // `npx` the file being used is `lib/commands/exec.js`
+ const commandName = configDoc.split('/').pop().split('.')[0].replace('npm-', '')
+ synopsis.push('\n```bash')
+
+ if (commandName) {
+ // special case for `npx`:
+ // `npx` is not technically a command in and of itself,
+ // so it just needs the usage and parameters of npm exec, and none of the aliases
+ if (commandName === 'npx') {
+ synopsis.push(usage.map(usageInfo => `npx ${usageInfo}`).join('\n'))
+ } else {
+ const baseCommand = `npm ${commandName}`
+ if (!usage) {
+ synopsis.push(baseCommand)
+ } else {
+ synopsis.push(usage.map(usageInfo => `${baseCommand} ${usageInfo}`).join('\n'))
+ }
+
+ const cmdAliases = Object.keys(aliases).reduce((p, c) => {
+ if (aliases[c] === commandName) {
+ p.push(c)
+ }
+ return p
+ }, [])
+
+ if (cmdAliases.length === 1) {
+ synopsis.push('')
+ synopsis.push(`alias: ${cmdAliases[0]}`)
+ } else if (cmdAliases.length > 1) {
+ synopsis.push('')
+ synopsis.push(`aliases: ${cmdAliases.join(', ')}`)
+ }
+ }
+ } else {
+ console.error(`could not determine command name from ${commandFile}`)
+ }
+
+ synopsis.push('```')
+ return synopsis.join('\n')
+}
+
+const addBetweenTags = (
+ doc,
+ startTag,
+ endTag,
+ body,
+ sourceFilepath = 'lib/utils/config/definitions.js') => {
+ const startSplit = doc.split(startTag)
+
+ if (startSplit.length !== 2) {
+ throw new Error('Did not find exactly one start tag')
+ }
+
+ const endSplit = startSplit[1].split(endTag)
+ if (endSplit.length !== 2) {
+ throw new Error('Did not find exactly one end tag')
+ }
+
+ return [
+ startSplit[0],
+ startTag,
+ '\n<!-- automatically generated, do not edit manually -->\n' +
+ '<!-- see ' + sourceFilepath + ' -->\n',
+ body,
+ '\n\n<!-- automatically generated, do not edit manually -->\n' +
+ '<!-- see ' + sourceFilepath + ' -->',
+ '\n\n',
+ endTag,
+ endSplit[1],
+ ].join('')
+}
+
+const TAGS = {
+ CONFIG: {
+ START: '<!-- AUTOGENERATED CONFIG DESCRIPTIONS START -->',
+ END: '<!-- AUTOGENERATED CONFIG DESCRIPTIONS END -->',
+ },
+ USAGE: {
+ START: '<!-- AUTOGENERATED USAGE DESCRIPTIONS START -->',
+ END: '<!-- AUTOGENERATED USAGE DESCRIPTIONS END -->',
+ },
+}
+
+const addDescriptions = ({ doc, params }) =>
+ addBetweenTags(doc, TAGS.CONFIG.START, TAGS.CONFIG.END, describeAll(params))
+
+const addUsageDescriptions = ({ doc, usage, configDoc, commandFile }) =>
+ addBetweenTags(doc, TAGS.USAGE.START, TAGS.USAGE.END,
+ describeUsage({ usage, configDoc, commandFile }),
+ commandFile
+ )
+
+const run = async (configDoc, commandFile) => {
+ try {
+ // Note: commands without params skip this whole process.
+ const { params, usage } = require(resolve(commandFile))
+
+ // always write SOMETHING so that Make sees the file is up to date.
+ const doc = await fs.readFile(configDoc, 'utf8')
+ const hasTag = doc.includes(TAGS.CONFIG.START)
+ const hasUsageTag = doc.includes(TAGS.USAGE.START)
+
+ if (params && params.length) {
+ let newDoc = hasTag ? addDescriptions({ doc, params }) : doc
+ newDoc = hasUsageTag
+ ? addUsageDescriptions({ doc: newDoc, usage, configDoc, commandFile })
+ : newDoc
+
+ if (!hasTag) {
+ console.error('WARNING: did not find config description section', configDoc)
+ }
+
+ if ((usage && usage.length) && !hasUsageTag) {
+ console.error('WARNING: did not find usage description section', configDoc)
+ }
+ await fs.writeFile(configDoc, newDoc)
+ }
+ } catch (err) {
+ console.error(`WARNING: file cannot be open: ${configDoc}`)
+ throw err
+ }
+}
+
+run(...process.argv.slice(2)).catch((err) => {
+ process.exitCode = 1
+ console.error(err)
+})
diff --git a/docs/bin/config-doc.js b/docs/bin/config-doc.js
new file mode 100644
index 000000000..1aa96e53c
--- /dev/null
+++ b/docs/bin/config-doc.js
@@ -0,0 +1,63 @@
+const fs = require('fs').promises
+const { resolve, relative } = require('path')
+const { shorthands, describeAll } = require('../lib/npm.js')
+
+const addBetweenTags = (doc, startTag, endTag, body) => {
+ const startSplit = doc.split(startTag)
+ if (startSplit.length !== 2) {
+ throw new Error('Did not find exactly one start tag')
+ }
+
+ const endSplit = startSplit[1].split(endTag)
+ if (endSplit.length !== 2) {
+ throw new Error('Did not find exactly one end tag')
+ }
+
+ return [
+ startSplit[0],
+ startTag,
+ '\n<!-- automatically generated, do not edit manually -->\n' +
+ '<!-- see lib/utils/config/definitions.js -->\n',
+ body,
+ '\n\n<!-- automatically generated, do not edit manually -->\n' +
+ '<!-- see lib/utils/config/definitions.js -->\n',
+ endTag,
+ endSplit[1],
+ ].join('')
+}
+
+const addDescriptions = doc => {
+ const startTag = '<!-- AUTOGENERATED CONFIG DESCRIPTIONS START -->'
+ const endTag = '<!-- AUTOGENERATED CONFIG DESCRIPTIONS END -->'
+ return addBetweenTags(doc, startTag, endTag, describeAll())
+}
+
+const addShorthands = doc => {
+ const startTag = '<!-- AUTOGENERATED CONFIG SHORTHANDS START -->'
+ const endTag = '<!-- AUTOGENERATED CONFIG SHORTHANDS END -->'
+ const body = Object.entries(shorthands)
+ .sort(([shorta, expansiona], [shortb, expansionb]) => {
+ // sort by what they're short FOR
+ return expansiona.join(' ').localeCompare(expansionb.join(' '), 'en') ||
+ shorta.localeCompare(shortb, 'en')
+ })
+ .map(([short, expansion]) => {
+ const dash = short.length === 1 ? '-' : '--'
+ return `* \`${dash}${short}\`: \`${expansion.join(' ')}\``
+ }).join('\n')
+ return addBetweenTags(doc, startTag, endTag, body)
+}
+
+const run = async (dir) => {
+ const configDoc = resolve(dir, '../content/using-npm/config.md')
+ const doc = await fs.readFile(configDoc, 'utf8')
+
+ await fs.writeFile(configDoc, addDescriptions(addShorthands(doc)))
+
+ return `updated ${relative(process.cwd(), configDoc)}`
+}
+
+run(__dirname).then(console.log).catch((err) => {
+ process.exitCode = 1
+ console.error(err)
+})
diff --git a/docs/bin/dockhand.js b/docs/bin/dockhand.js
index 4b359e1b6..56160136e 100644
--- a/docs/bin/dockhand.js
+++ b/docs/bin/dockhand.js
@@ -1,5 +1,3 @@
-#!/usr/bin/env node
-
const path = require('path')
const fs = require('fs')
const yaml = require('yaml')
@@ -7,35 +5,7 @@ const cmark = require('cmark-gfm')
const mdx = require('@mdx-js/mdx')
const mkdirp = require('mkdirp')
const jsdom = require('jsdom')
-const npm = require('../../lib/npm.js')
-
-const run = async function (rootDir) {
- const dir = (...p) => path.join(rootDir, '..', ...p)
-
- const config = require(dir('bin', 'config.json'))
- const template = fs.readFileSync(dir('bin', 'template.html'), 'utf-8')
- const nav = yaml.parse(fs.readFileSync(dir('nav.yml'), 'utf-8'))
-
- try {
- const navPaths = getNavigationPaths(nav)
- const fsPaths = await renderFilesystemPaths({
- input: dir('content'),
- output: dir('output'),
- config,
- template,
- })
-
- const navErrors = ensureNavigationComplete(navPaths, fsPaths)
- if (navErrors) {
- console.error(navErrors)
- process.exit(1)
- }
- } catch (error) {
- console.error(error)
- }
-}
-
-run(__dirname)
+const { version: VERSION } = require('../lib/npm.js')
function ensureNavigationComplete (navPaths, fsPaths) {
const unmatchedNav = {}
@@ -124,7 +94,7 @@ async function renderFile (root, outputRoot, childPath, { template, config }) {
const inputPath = path.join(root, childPath)
if (!inputPath.match(/\.md$/)) {
- console.log(`warning: unknown file type ${inputPath}, ignored`)
+ console.error(`warning: unknown file type ${inputPath}, ignored`)
return
}
@@ -140,7 +110,7 @@ async function renderFile (root, outputRoot, childPath, { template, config }) {
})
// Replace any tokens in the source
- md = md.replace(/@VERSION@/, npm.version)
+ md = md.replace(/@VERSION@/, VERSION)
// Render the markdown into an HTML snippet using a GFM renderer.
const content = cmark.renderHtmlSync(md, {
@@ -190,7 +160,7 @@ async function renderFile (root, outputRoot, childPath, { template, config }) {
return config[key.replace(/^config\./, '')]
default:
- console.log(`warning: unknown token '${token}' in ${inputPath}`)
+ console.error(`warning: unknown token '${token}' in ${inputPath}`)
return ''
}
})
@@ -323,3 +293,30 @@ class MarkdownError extends Error {
this.inner = inner
}
}
+
+const run = async function (rootDir) {
+ const dir = (...p) => path.join(rootDir, '..', ...p)
+
+ const config = require(dir('lib', 'config.json'))
+ const template = fs.readFileSync(dir('lib', 'template.html'), 'utf-8')
+ const nav = yaml.parse(fs.readFileSync(dir('nav.yml'), 'utf-8'))
+
+ const navPaths = getNavigationPaths(nav)
+ const fsPaths = await renderFilesystemPaths({
+ input: dir('content'),
+ output: dir('output'),
+ config,
+ template,
+ })
+
+ const navErrors = ensureNavigationComplete(navPaths, fsPaths)
+ if (navErrors) {
+ console.error(navErrors)
+ throw new Error('Nav Errors')
+ }
+}
+
+run(__dirname).catch((err) => {
+ process.exitCode = 1
+ console.error(err)
+})
diff --git a/docs/bin/docs-build.js b/docs/bin/docs-build.js
new file mode 100644
index 000000000..61343bfa4
--- /dev/null
+++ b/docs/bin/docs-build.js
@@ -0,0 +1,39 @@
+const fs = require('fs').promises
+const marked = require('marked-man')
+const { version: VERSION } = require('../lib/npm.js')
+
+function frontmatter (_, p1) {
+ const fm = {}
+
+ p1.split(/\r?\n/).forEach((kv) => {
+ const result = kv.match(/^([^\s:]+):\s*(.*)/)
+ if (result) {
+ fm[result[1]] = result[2]
+ }
+ })
+
+ return `# ${fm.title}(${fm.section}) - ${fm.description}`
+}
+
+function replacer (_, p1) {
+ return 'npm help ' + p1.replace(/npm /, '')
+}
+
+const run = async (src, dest = src) => {
+ const data = await fs.readFile(src, 'utf8')
+
+ const result = data.replace(/@VERSION@/g, VERSION)
+ .replace(/^<!--.*-->$/gm, '')
+ .replace(/^---\n([\s\S]+\n)---/, frontmatter)
+ .replace(/\[([^\]]+)\]\(\/commands\/([^)]+)\)/g, replacer)
+ .replace(/\[([^\]]+)\]\(\/configuring-npm\/([^)]+)\)/g, replacer)
+ .replace(/\[([^\]]+)\]\(\/using-npm\/([^)]+)\)/g, replacer)
+ .trim()
+
+ await fs.writeFile(dest, marked(result), 'utf8')
+}
+
+run(...process.argv.slice(2)).catch((err) => {
+ process.exitCode = 1
+ console.error(err)
+})
diff --git a/docs/bin/config.json b/docs/lib/config.json
index c9f183e4e..c9f183e4e 100644
--- a/docs/bin/config.json
+++ b/docs/lib/config.json
diff --git a/docs/lib/npm.js b/docs/lib/npm.js
new file mode 100644
index 000000000..fb801a17b
--- /dev/null
+++ b/docs/lib/npm.js
@@ -0,0 +1,14 @@
+const { definitions, shorthands, describeAll } = require('../../lib/utils/config/index.js')
+const { aliases } = require('../../lib/utils/cmd-list')
+const Npm = require('../../lib/npm.js')
+
+// These are all the npm internals depended on by the docs scripts. If these change
+// the associated targets should also be updated in the Makefile.
+
+module.exports = {
+ definitions,
+ shorthands,
+ describeAll,
+ aliases,
+ version: Npm.version,
+}
diff --git a/docs/bin/template.html b/docs/lib/template.html
index be3bafd61..be3bafd61 100644
--- a/docs/bin/template.html
+++ b/docs/lib/template.html
diff --git a/docs/package.json b/docs/package.json
index 9bd06f094..037db15a0 100644
--- a/docs/package.json
+++ b/docs/package.json
@@ -4,7 +4,6 @@
"version": "1.0.0",
"private": true,
"scripts": {
- "build": "node bin/dockhand",
"lint": "eslint \"**/*.js\"",
"postlint": "template-oss-check",
"template-oss-apply": "template-oss-apply --force",
@@ -30,12 +29,14 @@
"jsdom": "^18.1.0",
"marked-man": "^0.7.0",
"tap": "^15.2.3",
+ "which": "^2.0.2",
"yaml": "^1.10.0"
},
"author": "GitHub Inc.",
"license": "ISC",
"files": [
"bin/",
+ "lib/",
"content/",
"nav.yml"
],
@@ -45,13 +46,14 @@
"tap": {
"statements": 81,
"branches": 72,
- "functions": 80,
+ "functions": 75,
"lines": 81
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
"distPaths": [
"bin/",
+ "lib/",
"content/",
"nav.yml"
],
diff --git a/docs/test/index.js b/docs/test/index.js
index fab9748a3..57524327b 100644
--- a/docs/test/index.js
+++ b/docs/test/index.js
@@ -9,24 +9,24 @@ const output = join(cwd, 'output')
const rmOutput = () => fs.rm(output, { recursive: true, force: true }).catch(() => {})
-const spawnNpm = (...args) => {
+const spawnNpm = (cmd, ...args) => {
// remove npm config when spawning so config set by test commands don't interfere
const env = Object.entries(process.env)
.filter(([k]) => k.toLowerCase() !== 'npm_config_ignore_scripts')
- return spawn(which('npm'), args, {
+ return spawn(which(cmd), args, {
env: Object.fromEntries(env),
stdioString: true,
cwd,
})
}
-t.before(() => spawnNpm('rebuild', 'cmark-gfm'))
+t.before(() => spawnNpm('npm', 'rebuild', 'cmark-gfm'))
t.beforeEach(() => rmOutput())
t.test('docs', async (t) => {
t.rejects(() => fs.stat(output))
- const docs = await spawnNpm('run', 'build')
+ const docs = await spawnNpm('node', join('bin', 'dockhand'))
t.equal(docs.code, 0)
t.ok((await fs.stat(output)).isDirectory())
})