File Explorer

/proc/self/root/proc/thread-self/root/proc/1/root/node24/lib/node_modules/npm/docs/lib

This explorer reads the filesystem of the server it runs on, so /workspace/user isn't present here. Browsing and the terminal still work against this server's own disk from /.

index.js9.3 KB · 304 lines
const localeCompare = require('@isaacs/string-locale-compare')('en')const { join, basename, resolve } = require('path')const transformHTML = require('./transform-html.js')const { version } = require('../../lib/npm.js')const { aliases } = require('../../lib/utils/cmd-list')const { shorthands, definitions } = require('@npmcli/config/lib/definitions') const DOC_EXT = '.md' const TAGS = {  CONFIG: '<!-- AUTOGENERATED CONFIG DESCRIPTIONS -->',  USAGE: '<!-- AUTOGENERATED USAGE DESCRIPTIONS -->',  SHORTHANDS: '<!-- AUTOGENERATED CONFIG SHORTHANDS -->',} const assertPlaceholder = (src, path, placeholder) => {  if (!src.includes(placeholder)) {    throw new Error(      `Cannot replace ${placeholder} in ${path} due to missing placeholder`    )  }  return placeholder} // Default command loader - loads commands from lib/commandsconst defaultCommandLoader = (name) => {  return require(`../../lib/commands/${name}`)} // Load a command using the provided loader or defaultconst getCommand = (name, commandLoader = defaultCommandLoader) => {  return commandLoader(name)} // Resolve definitions for a command - use definitions if present, otherwise build from paramsconst resolveDefinitions = (command) => {  // If command has definitions, use them directly (ignore params)  if (command.definitions && Object.keys(command.definitions).length > 0) {    return command.definitions  }   // Otherwise build from params using global definitions  if (command.params) {    const resolved = {}    for (const param of command.params) {      if (definitions[param]) {        resolved[param] = definitions[param]      }    }    return resolved  }   return {}} const getCommandByDoc = (docFile, docExt, commandLoader = defaultCommandLoader) => {  // 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 name = basename(docFile, docExt).replace('npm-', '')   if (name === 'npm') {    return {      name,      definitions: [],      usage: 'npm',    }  }   // special case for `npx`:  // `npx` is not technically a command in and of itself,  // so it just needs the usage of npm exec  const srcName = name === 'npx' ? 'exec' : name  const command = getCommand(srcName, commandLoader)  const { usage = [''], workspaces } = command  const usagePrefix = name === 'npx' ? 'npx' : `npm ${name}`   // Resolve definitions - handles exclusive params expansion  const commandDefs = resolveDefinitions(command)  const resolvedDefs = {}  for (const [key, def] of Object.entries(commandDefs)) {    resolvedDefs[key] = def    // Handle exclusive params    if (def.exclusive) {      for (const e of def.exclusive) {        if (!resolvedDefs[e] && definitions[e]) {          resolvedDefs[e] = definitions[e]        }      }    }  }   return {    name,    workspaces,    definitions: name === 'npx' ? {} : resolvedDefs,    usage: usage.map(u => `${usagePrefix} ${u}`.trim()).join('\n'),  }} const replaceVersion = (src) => src.replace(/@VERSION@/g, version) const replaceUsage = (src, { path, commandLoader }) => {  const replacer = assertPlaceholder(src, path, TAGS.USAGE)  const { usage, name, workspaces } = getCommandByDoc(path, DOC_EXT, commandLoader)   const synopsis = ['```bash', usage]   const cmdAliases = Object.keys(aliases).reduce((p, c) => {    if (aliases[c] === name) {      p.push(c)    }    return p  }, [])   if (cmdAliases.length === 1) {    synopsis.push('', `alias: ${cmdAliases[0]}`)  } else if (cmdAliases.length > 1) {    synopsis.push('', `aliases: ${cmdAliases.join(', ')}`)  }   synopsis.push('```')   if (!workspaces) {    synopsis.push('', 'Note: This command is unaware of workspaces.')  }   return src.replace(replacer, synopsis.join('\n'))} // Helper to generate a markdown table from definitionsconst generateFlagsTable = (definitionPool) => {  const rows = Object.keys(definitionPool).map((n) => {    const def = definitionPool[n]    const flags = [`\`--${def.key}\``]    if (def.alias) {      flags.push(...def.alias.map(a => `\`--${a}\``))    }    if (def.short) {      flags.push(`\`-${def.short}\``)    }    const flagsStr = flags.join(', ')    let defaultVal = def.defaultDescription    if (!defaultVal) {      defaultVal = String(def.default)    }    let typeVal = def.typeDescription || String(def.type)    if (def.required) {      typeVal = `${typeVal} (required)`    }    const desc = (def.description || '').replace(/\n/g, ' ').trim()    return `| ${flagsStr} | ${defaultVal} | ${typeVal} | ${desc} |`  })   return [    '| Flag | Default | Type | Description |',    '| --- | --- | --- | --- |',    ...rows,  ].join('\n')} const replaceDefinitions = (src, { path, commandLoader }) => {  const { definitions: commandDefs, name } = getCommandByDoc(path, DOC_EXT, commandLoader)   let subcommands = {}  try {    const command = getCommand(name, commandLoader)    subcommands = command.subcommands || {}  } catch {    // Command doesn't exist  }   // If no definitions and no subcommands, nothing to replace  if (Object.keys(commandDefs).length === 0 && Object.keys(subcommands).length === 0) {    return src  }   // Assert placeholder is present  const replacer = assertPlaceholder(src, path, TAGS.CONFIG)   // If command has subcommands, generate sections for each subcommand  if (Object.keys(subcommands).length > 0) {    const subcommandSections = Object.entries(subcommands).map(([subName, SubCommand]) => {      const subUsage = SubCommand.usage || []      const subDefs = resolveDefinitions(SubCommand)       const parts = [`### \`npm ${name} ${subName}\``, '']       if (SubCommand.description) {        parts.push(SubCommand.description, '')      }       // Add usage/synopsis      if (subUsage.length > 0) {        parts.push('#### Synopsis', '', '```bash')        subUsage.forEach(u => {          parts.push(`npm ${name} ${subName} ${u}`.trim())        })        parts.push('```', '')      }       // Add flags section if definitions exist      if (Object.keys(subDefs).length > 0) {        parts.push('#### Flags', '')        parts.push(generateFlagsTable(subDefs), '')      }       return parts.join('\n')    })     return src.replace(replacer, subcommandSections.join('\n'))  }   // For commands without subcommands - commandDefs must be non-empty here  // (we would have returned early at line 175 if both were empty)  const paramDescriptions = Object.values(commandDefs)    .map(def => def.describe())   return src.replace(replacer, paramDescriptions.join('\n\n'))} const replaceConfig = (src, { path }) => {  const replacer = assertPlaceholder(src, path, TAGS.CONFIG)   // sort not-deprecated ones to the top  /* istanbul ignore next - typically already sorted in the definitions file,   * but this is here so that our help doc will stay consistent if we decide   * to move them around. */  const sort = ([keya, { deprecated: depa }], [keyb, { deprecated: depb }]) => {    return depa && !depb ? 1      : !depa && depb ? -1      : localeCompare(keya, keyb)  }   const allConfig = Object.entries(definitions).sort(sort)    .map(([, def]) => def.describe())    .join('\n\n')   return src.replace(replacer, allConfig)} const replaceShorthands = (src, { path }) => {  const replacer = assertPlaceholder(src, path, TAGS.SHORTHANDS)   const sh = Object.entries(shorthands)    .sort(([shorta, expansiona], [shortb, expansionb]) =>      // sort by what they're short FOR      localeCompare(expansiona.join(' '), expansionb.join(' ')) || localeCompare(shorta, shortb)    )    .map(([short, expansion]) => {      // XXX: this is incorrect. we have multicharacter flags like `-iwr` that      // can only be set with a single dash      const dash = short.length === 1 ? '-' : '--'      return `* \`${dash}${short}\`: \`${expansion.join(' ')}\``    })   return src.replace(replacer, sh.join('\n'))} const replaceHelpLinks = (src) => {  // replaces markdown links with equivalent-ish npm help commands  return src.replace(    /\[`?([\w\s-]+)`?\]\(\/(?:commands|configuring-npm|using-npm)\/(?:[\w\s-]+)\)/g,    (_, p1) => {      const term = p1.replace(/npm\s/g, '').replace(/\s+/g, ' ').trim()      const help = `npm help ${term.includes(' ') ? `"${term}"` : term}`      return help    }  )} const transformMan = (src, { data, unified, remarkParse, remarkMan }) => unified()  .use(remarkParse)  .use(remarkMan, { version: `NPM@${version}` })  .processSync(`# ${data.title}(${data.section}) - ${data.description}\n\n${src}`)  .toString() const manPath = (name, { data }) => join(`man${data.section}`, `${name}.${data.section}`) const transformMd = (src, { frontmatter }) => ['---', frontmatter, '---', '', src].join('\n') module.exports = {  DOC_EXT,  TAGS,  paths: {    content: resolve(__dirname, 'content'),    nav: resolve(__dirname, 'content', 'nav.yml'),    template: resolve(__dirname, 'template.html'),    man: resolve(__dirname, '..', '..', 'man'),    html: resolve(__dirname, '..', 'output'),    md: resolve(__dirname, '..', 'content'),  },  usage: replaceUsage,  definitions: replaceDefinitions,  config: replaceConfig,  shorthands: replaceShorthands,  version: replaceVersion,  helpLinks: replaceHelpLinks,  man: transformMan,  manPath: manPath,  md: transformMd,  html: transformHTML,}