diff options
author | Wassim Chegham <1699357+manekinekko@users.noreply.github.com> | 2022-02-24 20:46:37 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-02-24 20:46:37 +0300 |
commit | 6b68c1aaa282205eb4d47dbc81909c11851f7e06 (patch) | |
tree | a5a2ddafe61e5e475913a316a3ca59893629f986 /scripts | |
parent | d438d61d4f689966de8f964afe212d1319b8d460 (diff) |
docs: auto-generate npm usage for each command (#4450)
Closes #4189
* docs: auto-generate synopsis sections
* feat: improve usage auto-generation'
* chore: auto-generate npm usage for each command
* docs: print default usage when usage is missing
* docs: add special case for npx
* fix: remove optional chaining
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/config-doc-command.js | 111 |
1 files changed, 93 insertions, 18 deletions
diff --git a/scripts/config-doc-command.js b/scripts/config-doc-command.js index 9db026f30..af008b7e1 100644 --- a/scripts/config-doc-command.js +++ b/scripts/config-doc-command.js @@ -1,21 +1,78 @@ const { definitions } = require('../lib/utils/config/index.js') +const usageFn = require('../lib/utils/usage.js') const { writeFileSync, readFileSync } = require('fs') const { resolve } = require('path') const configDoc = process.argv[2] const commandFile = process.argv[3] +const TAGS = { + CONFIG: { + START: '<!-- AUTOGENERATED CONFIG DESCRIPTIONS START -->', + END: '<!-- AUTOGENERATED CONFIG DESCRIPTIONS END -->', + }, + USAGE: { + START: '<!-- AUTOGENERATED USAGE DESCRIPTIONS START -->', + END: '<!-- AUTOGENERATED USAGE DESCRIPTIONS END -->', + }, +} + // Note: commands without params skip this whole process. -const { params } = require(resolve(commandFile)) +const { + params, + usage, +} = require(resolve(commandFile)) -const describeAll = () => - params.map(name => definitions[name].describe()).join( +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 addBetweenTags = (doc, startTag, endTag, body) => { +const describeUsage = ({ usage }) => { + 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 aliases = usageFn(commandName, '').trim() + if (aliases) { + synopsis.push(`\n${aliases}`) + } + } + } 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') } @@ -29,27 +86,45 @@ const addBetweenTags = (doc, startTag, endTag, body) => { startSplit[0], startTag, '\n<!-- automatically generated, do not edit manually -->\n' + - '<!-- see lib/utils/config/definitions.js -->\n', + '<!-- see ' + sourceFilepath + ' -->\n', body, '\n\n<!-- automatically generated, do not edit manually -->\n' + - '<!-- see lib/utils/config/definitions.js -->', + '<!-- see ' + sourceFilepath + ' -->', '\n\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 addDescriptions = doc => + addBetweenTags(doc, TAGS.CONFIG.START, TAGS.CONFIG.END, describeAll(params)) + +const addUsageDescriptions = doc => + addBetweenTags(doc, TAGS.USAGE.START, TAGS.USAGE.END, + describeUsage({ usage }), + commandFile + ) -// always write SOMETHING so that Make sees the file is up to date. -const doc = readFileSync(configDoc, 'utf8') -const hasTag = doc.includes('<!-- AUTOGENERATED CONFIG DESCRIPTIONS START -->') -const newDoc = params && hasTag ? addDescriptions(doc) : doc -if (params && !hasTag) { - console.error('WARNING: did not find config description section', configDoc) +try { + // always write SOMETHING so that Make sees the file is up to date. + const doc = readFileSync(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) : doc + newDoc = hasUsageTag ? addUsageDescriptions(newDoc) : 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) + } + writeFileSync(configDoc, newDoc) + } +} catch (err) { + console.error(`WARNING: file cannot be open: ${configDoc}`) + console.error(err) } -writeFileSync(configDoc, newDoc) |