@@ -32,6 +32,27 @@ const getCommand = (name, commandLoader = defaultCommandLoader) => {
3232 return commandLoader ( name )
3333}
3434
35+ // Resolve definitions for a command - use definitions if present, otherwise build from params
36+ const resolveDefinitions = ( command ) => {
37+ // If command has definitions, use them directly (ignore params)
38+ if ( command . definitions && Object . keys ( command . definitions ) . length > 0 ) {
39+ return command . definitions
40+ }
41+
42+ // Otherwise build from params using global definitions
43+ if ( command . params ) {
44+ const resolved = { }
45+ for ( const param of command . params ) {
46+ if ( definitions [ param ] ) {
47+ resolved [ param ] = definitions [ param ]
48+ }
49+ }
50+ return resolved
51+ }
52+
53+ return { }
54+ }
55+
3556const getCommandByDoc = ( docFile , docExt , commandLoader = defaultCommandLoader ) => {
3657 // Grab the command name from the *.md filename
3758 // NOTE: We cannot use the name property command file because in the case of
@@ -41,7 +62,7 @@ const getCommandByDoc = (docFile, docExt, commandLoader = defaultCommandLoader)
4162 if ( name === 'npm' ) {
4263 return {
4364 name,
44- params : null ,
65+ definitions : { } ,
4566 usage : 'npm' ,
4667 }
4768 }
@@ -51,19 +72,19 @@ const getCommandByDoc = (docFile, docExt, commandLoader = defaultCommandLoader)
5172 // so it just needs the usage of npm exec
5273 const srcName = name === 'npx' ? 'exec' : name
5374 const command = getCommand ( srcName , commandLoader )
54- const { params, usage = [ '' ] , workspaces } = command
55- const commandDefinitions = command . definitions || { }
56- const definitionPool = { ...definitions , ...commandDefinitions }
75+ const { usage = [ '' ] , workspaces } = command
5776 const usagePrefix = name === 'npx' ? 'npx' : `npm ${ name } `
58- if ( params ) {
59- for ( const param of params ) {
60- // Check command-specific definitions first, fall back to global definitions
61- const paramDef = definitionPool [ param ]
62- if ( paramDef && paramDef . exclusive ) {
63- for ( const e of paramDef . exclusive ) {
64- if ( ! params . includes ( e ) ) {
65- params . splice ( params . indexOf ( param ) + 1 , 0 , e )
66- }
77+
78+ // Resolve definitions - handles exclusive params expansion
79+ const commandDefs = resolveDefinitions ( command )
80+ const resolvedDefs = { }
81+ for ( const [ key , def ] of Object . entries ( commandDefs ) ) {
82+ resolvedDefs [ key ] = def
83+ // Handle exclusive params
84+ if ( def . exclusive ) {
85+ for ( const e of def . exclusive ) {
86+ if ( ! resolvedDefs [ e ] && definitions [ e ] ) {
87+ resolvedDefs [ e ] = definitions [ e ]
6788 }
6889 }
6990 }
@@ -72,7 +93,7 @@ const getCommandByDoc = (docFile, docExt, commandLoader = defaultCommandLoader)
7293 return {
7394 name,
7495 workspaces,
75- params : name === 'npx' ? null : params ,
96+ definitions : name === 'npx' ? { } : resolvedDefs ,
7697 usage : usage . map ( u => `${ usagePrefix } ${ u } ` . trim ( ) ) . join ( '\n' ) ,
7798 }
7899}
@@ -138,33 +159,30 @@ const generateFlagsTable = (definitionPool) => {
138159 ] . join ( '\n' )
139160}
140161
141- const replaceParams = ( src , { path, commandLoader } ) => {
142- const { params , name } = getCommandByDoc ( path , DOC_EXT , commandLoader )
162+ const replaceDefinitions = ( src , { path, commandLoader } ) => {
163+ const { definitions : commandDefs , name } = getCommandByDoc ( path , DOC_EXT , commandLoader )
143164
144- // Load command to get command-specific definitions and subcommands if they exist
145- let commandDefinitions = { }
146165 let subcommands = { }
147166 try {
148167 const command = getCommand ( name , commandLoader )
149- commandDefinitions = command . definitions || { }
150168 subcommands = command . subcommands || { }
151169 } catch {
152- // If command doesn't exist or has no definitions, continue with global definitions only
170+ // Command doesn't exist
153171 }
154172
155- // If no params and no subcommands, nothing to replace
156- if ( ! params && Object . keys ( subcommands ) . length === 0 ) {
173+ // If no definitions and no subcommands, nothing to replace
174+ if ( Object . keys ( commandDefs ) . length === 0 && Object . keys ( subcommands ) . length === 0 ) {
157175 return src
158176 }
159177
160- // Assert placeholder is present - commands with params must have the config placeholder
178+ // Assert placeholder is present
161179 const replacer = assertPlaceholder ( src , path , TAGS . CONFIG )
162180
163181 // If command has subcommands, generate sections for each subcommand
164182 if ( Object . keys ( subcommands ) . length > 0 ) {
165183 const subcommandSections = Object . entries ( subcommands ) . map ( ( [ subName , SubCommand ] ) => {
166184 const subUsage = SubCommand . usage || [ ]
167- const subDefinitions = SubCommand . definitions || { }
185+ const subDefs = resolveDefinitions ( SubCommand )
168186
169187 const parts = [ `### \`npm ${ name } ${ subName } \`` , '' ]
170188
@@ -181,10 +199,10 @@ const replaceParams = (src, { path, commandLoader }) => {
181199 parts . push ( '```' , '' )
182200 }
183201
184- // Add flags section with all parameters combined
185- if ( Object . keys ( subDefinitions ) . length > 0 ) {
202+ // Add flags section if definitions exist
203+ if ( Object . keys ( subDefs ) . length > 0 ) {
186204 parts . push ( '#### Flags' , '' )
187- parts . push ( generateFlagsTable ( subDefinitions ) , '' )
205+ parts . push ( generateFlagsTable ( subDefs ) , '' )
188206 }
189207
190208 return parts . join ( '\n' )
@@ -193,21 +211,10 @@ const replaceParams = (src, { path, commandLoader }) => {
193211 return src . replace ( replacer , subcommandSections . join ( '\n' ) )
194212 }
195213
196- // Original behavior for commands without subcommands but with params
197- /* istanbul ignore if - all commands with no subcommands have params */
198- if ( ! params ) {
199- return src
200- }
201-
202- // Build definitions object from params using global definitions pool
203- const allDefinitions = { ...definitions , ...commandDefinitions }
204- const paramDescriptions = [ ]
205- for ( const param of params ) {
206- if ( allDefinitions [ param ] ) {
207- const def = allDefinitions [ param ]
208- paramDescriptions . push ( def . describe ( ) )
209- }
210- }
214+ // For commands without subcommands - commandDefs must be non-empty here
215+ // (we would have returned early at line 175 if both were empty)
216+ const paramDescriptions = Object . values ( commandDefs )
217+ . map ( def => def . describe ( ) )
211218
212219 return src . replace ( replacer , paramDescriptions . join ( '\n\n' ) )
213220}
@@ -284,7 +291,7 @@ module.exports = {
284291 md : resolve ( __dirname , '..' , 'content' ) ,
285292 } ,
286293 usage : replaceUsage ,
287- params : replaceParams ,
294+ definitions : replaceDefinitions ,
288295 config : replaceConfig ,
289296 shorthands : replaceShorthands ,
290297 version : replaceVersion ,
0 commit comments