@@ -144,8 +144,7 @@ class WebpackCLI {
144
144
flags = `${ flags } <value${ isMultiple ? '...' : '' } >` ;
145
145
}
146
146
147
- // TODO need to fix on webpack-dev-server side
148
- // `describe` used by `webpack-dev-server`
147
+ // TODO `describe` used by `webpack-dev-server@3`
149
148
const description = option . description || option . describe || '' ;
150
149
const defaultValue = option . defaultValue ;
151
150
@@ -236,16 +235,14 @@ class WebpackCLI {
236
235
usage : '[options]' ,
237
236
} ;
238
237
const versionCommandOptions = {
239
- name : 'version' ,
238
+ name : 'version [commands...] ' ,
240
239
alias : 'v' ,
241
240
description : "Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands." ,
242
- usage : '[commands...]' ,
243
241
} ;
244
242
const helpCommandOptions = {
245
- name : 'help' ,
243
+ name : 'help [command] [option] ' ,
246
244
alias : 'h' ,
247
245
description : 'Display help for commands and options.' ,
248
- usage : '[command]' ,
249
246
} ;
250
247
// Built-in external commands
251
248
const externalBuiltInCommandsInfo = [
@@ -287,24 +284,34 @@ class WebpackCLI {
287
284
] ;
288
285
289
286
const knownCommands = [ buildCommandOptions , versionCommandOptions , helpCommandOptions , ...externalBuiltInCommandsInfo ] ;
287
+ const getCommandName = ( name ) => name . split ( ' ' ) [ 0 ] ;
290
288
const isKnownCommand = ( name ) =>
291
289
knownCommands . find (
292
290
( command ) =>
293
- command . name === name || ( Array . isArray ( command . alias ) ? command . alias . includes ( name ) : command . alias === name ) ,
291
+ getCommandName ( command . name ) === name ||
292
+ ( Array . isArray ( command . alias ) ? command . alias . includes ( name ) : command . alias === name ) ,
294
293
) ;
295
294
const isBuildCommand = ( name ) =>
296
- buildCommandOptions . name === name ||
295
+ getCommandName ( buildCommandOptions . name ) === name ||
297
296
( Array . isArray ( buildCommandOptions . alias ) ? buildCommandOptions . alias . includes ( name ) : buildCommandOptions . alias === name ) ;
298
297
const isHelpCommand = ( name ) =>
299
- helpCommandOptions . name === name ||
298
+ getCommandName ( helpCommandOptions . name ) === name ||
300
299
( Array . isArray ( helpCommandOptions . alias ) ? helpCommandOptions . alias . includes ( name ) : helpCommandOptions . alias === name ) ;
301
300
const isVersionCommand = ( name ) =>
302
- versionCommandOptions . name === name ||
301
+ getCommandName ( versionCommandOptions . name ) === name ||
303
302
( Array . isArray ( versionCommandOptions . alias )
304
303
? versionCommandOptions . alias . includes ( name )
305
304
: versionCommandOptions . alias === name ) ;
306
305
const findCommandByName = ( name ) =>
307
306
this . program . commands . find ( ( command ) => name === command . name ( ) || command . alias ( ) . includes ( name ) ) ;
307
+ const isOption = ( value ) => value . startsWith ( '-' ) ;
308
+ const isGlobalOption = ( value ) =>
309
+ value === '--color' ||
310
+ value === '--no-color' ||
311
+ value === '-v' ||
312
+ value === '--version' ||
313
+ value === '-h' ||
314
+ value === '--help' ;
308
315
309
316
const getCommandNameAndOptions = ( args ) => {
310
317
let commandName ;
@@ -313,7 +320,7 @@ class WebpackCLI {
313
320
let allowToSearchCommand = true ;
314
321
315
322
args . forEach ( ( arg ) => {
316
- if ( ! arg . startsWith ( '-' ) && allowToSearchCommand ) {
323
+ if ( ! isOption ( arg ) && allowToSearchCommand ) {
317
324
commandName = arg ;
318
325
319
326
allowToSearchCommand = false ;
@@ -491,9 +498,7 @@ class WebpackCLI {
491
498
) ;
492
499
493
500
possibleCommandNames . forEach ( ( possibleCommandName ) => {
494
- const isOption = possibleCommandName . startsWith ( '-' ) ;
495
-
496
- if ( ! isOption ) {
501
+ if ( ! isOption ( possibleCommandName ) ) {
497
502
return ;
498
503
}
499
504
@@ -544,9 +549,7 @@ class WebpackCLI {
544
549
"Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands." ,
545
550
) ;
546
551
547
- // Default global `help` command
548
- const outputHelp = async ( options , isVerbose , program ) => {
549
- const isGlobal = options . length === 0 ;
552
+ const outputHelp = async ( options , isVerbose , isHelpCommandSyntax , program ) => {
550
553
const hideVerboseOptions = ( command ) => {
551
554
command . options = command . options . filter ( ( option ) => {
552
555
const foundOption = flags . find ( ( flag ) => {
@@ -564,11 +567,40 @@ class WebpackCLI {
564
567
return true ;
565
568
} ) ;
566
569
} ;
570
+ const outputGlobalOptions = ( ) => {
571
+ const programHelpInformation = program . helpInformation ( ) ;
572
+ const globalOptions = programHelpInformation . match ( / O p t i o n s : \n (?< globalOptions > .+ ) \n C o m m a n d s : \n / s) ;
573
+
574
+ if ( globalOptions && globalOptions . groups . globalOptions ) {
575
+ logger . raw ( '\nGlobal options:' ) ;
576
+ logger . raw ( globalOptions . groups . globalOptions . trimRight ( ) ) ;
577
+ }
578
+ } ;
579
+ const outputGlobalCommands = ( ) => {
580
+ const programHelpInformation = program . helpInformation ( ) ;
581
+ const globalCommands = programHelpInformation . match ( / C o m m a n d s : \n (?< globalCommands > .+ ) / s) ;
582
+
583
+ if ( globalCommands . groups . globalCommands ) {
584
+ logger . raw ( '\nCommands:' ) ;
585
+ logger . raw (
586
+ globalCommands . groups . globalCommands
587
+ . trimRight ( )
588
+ // `commander` doesn't support multiple alias in help
589
+ . replace ( 'build|bundle [options] ' , 'build|bundle|b [options]' ) ,
590
+ ) ;
591
+ }
592
+ } ;
593
+ const outputIncorrectUsageOfHelp = ( ) => {
594
+ logger . error ( 'Incorrect use of help' ) ;
595
+ logger . error ( "Please use: 'webpack help [command] [option]' | 'webpack [command] --help'" ) ;
596
+ logger . error ( "Run 'webpack --help' to see available commands and options" ) ;
597
+ process . exit ( 2 ) ;
598
+ } ;
567
599
568
- if ( isGlobal ) {
600
+ if ( options . length === 0 ) {
569
601
await Promise . all (
570
602
knownCommands . map ( ( knownCommand ) => {
571
- return loadCommandByName ( knownCommand . name ) ;
603
+ return loadCommandByName ( getCommandName ( knownCommand . name ) ) ;
572
604
} ) ,
573
605
) ;
574
606
@@ -588,20 +620,11 @@ class WebpackCLI {
588
620
) ;
589
621
590
622
logger . raw ( helpInformation ) ;
591
- } else {
592
- const [ name , ...optionsWithoutCommandName ] = options ;
593
623
594
- if ( name . startsWith ( '-' ) ) {
595
- logger . error ( `Unknown option '${ name } '` ) ;
596
- logger . error ( "Run 'webpack --help' to see available commands and options" ) ;
597
- process . exit ( 2 ) ;
598
- }
599
-
600
- optionsWithoutCommandName . forEach ( ( option ) => {
601
- logger . error ( `Unknown option '${ option } '` ) ;
602
- logger . error ( "Run 'webpack --help' to see available commands and options" ) ;
603
- process . exit ( 2 ) ;
604
- } ) ;
624
+ outputGlobalOptions ( ) ;
625
+ outputGlobalCommands ( ) ;
626
+ } else if ( options . length === 1 && ! isOption ( options [ 0 ] ) ) {
627
+ const name = options [ 0 ] ;
605
628
606
629
await loadCommandByName ( name ) ;
607
630
@@ -629,26 +652,71 @@ class WebpackCLI {
629
652
}
630
653
631
654
logger . raw ( helpInformation ) ;
632
- }
633
655
634
- const programHelpInformation = program . helpInformation ( ) ;
635
- const globalOptions = programHelpInformation . match ( / O p t i o n s : \n (?< globalOptions > .+ ) \n C o m m a n d s : \n / s) ;
656
+ outputGlobalOptions ( ) ;
657
+ } else if ( isHelpCommandSyntax ) {
658
+ let commandName ;
659
+ let optionName ;
636
660
637
- if ( globalOptions && globalOptions . groups . globalOptions ) {
638
- logger . raw ( '\nGlobal options:' ) ;
639
- logger . raw ( globalOptions . groups . globalOptions . trimRight ( ) ) ;
640
- }
661
+ if ( options . length === 1 ) {
662
+ commandName = buildCommandOptions . name ;
663
+ optionName = options [ 0 ] ;
664
+ } else if ( options . length === 2 ) {
665
+ commandName = options [ 0 ] ;
666
+ optionName = options [ 1 ] ;
667
+
668
+ if ( isOption ( commandName ) ) {
669
+ outputIncorrectUsageOfHelp ( ) ;
670
+ }
671
+ } else {
672
+ outputIncorrectUsageOfHelp ( ) ;
673
+ }
674
+
675
+ await loadCommandByName ( commandName ) ;
676
+
677
+ const command = isGlobalOption ( optionName ) ? this . program : findCommandByName ( commandName ) ;
678
+
679
+ if ( ! command ) {
680
+ logger . error ( `Can't find and load command '${ commandName } '` ) ;
681
+ logger . error ( "Run 'webpack --help' to see available commands and options" ) ;
682
+ process . exit ( 2 ) ;
683
+ }
684
+
685
+ const option = command . options . find ( ( option ) => option . short === optionName || option . long === optionName ) ;
641
686
642
- const globalCommands = programHelpInformation . match ( / C o m m a n d s : \n (?< globalCommands > .+ ) / s) ;
687
+ if ( ! option ) {
688
+ logger . error ( `Unknown option '${ optionName } '` ) ;
689
+ logger . error ( "Run 'webpack --help' to see available commands and options" ) ;
690
+ process . exit ( 2 ) ;
691
+ }
692
+
693
+ const nameOutput =
694
+ option . flags . replace ( / ^ .+ [ [ < ] / , '' ) . replace ( / ( \. \. \. ) ? [ \] > ] .* $ / , '' ) + ( option . variadic === true ? '...' : '' ) ;
695
+ const value = option . required ? '<' + nameOutput + '>' : option . optional ? '[' + nameOutput + ']' : '' ;
643
696
644
- if ( isGlobal && globalCommands . groups . globalCommands ) {
645
- logger . raw ( '\nCommands:' ) ;
646
697
logger . raw (
647
- globalCommands . groups . globalCommands
648
- . trimRight ( )
649
- // `commander` doesn't support multiple alias in help
650
- . replace ( 'build|bundle [options] ' , 'build|bundle|b [options]' ) ,
698
+ `Usage: webpack${ isBuildCommand ( commandName ) ? '' : ` ${ commandName } ` } ${ option . long } ${ value ? ` ${ value } ` : '' } ` ,
651
699
) ;
700
+
701
+ if ( option . short ) {
702
+ logger . raw (
703
+ `Short: webpack${ isBuildCommand ( commandName ) ? '' : ` ${ commandName } ` } ${ option . short } ${ value ? ` ${ value } ` : '' } ` ,
704
+ ) ;
705
+ }
706
+
707
+ if ( option . description ) {
708
+ logger . raw ( `Description: ${ option . description } ` ) ;
709
+ }
710
+
711
+ if ( ! option . negate && options . defaultValue ) {
712
+ logger . raw ( `Default value: ${ JSON . stringify ( option . defaultValue ) } ` ) ;
713
+ }
714
+
715
+ // TODO implement this after refactor cli arguments
716
+ // logger.raw('Possible values: foo | bar');
717
+ // logger.raw('Documentation: https://webpack.js.org/option/name/');
718
+ } else {
719
+ outputIncorrectUsageOfHelp ( ) ;
652
720
}
653
721
654
722
logger . raw ( "\nTo see list of all supported commands and options run 'webpack --help=verbose'.\n" ) ;
@@ -678,7 +746,9 @@ class WebpackCLI {
678
746
679
747
const opts = program . opts ( ) ;
680
748
681
- if ( opts . help || isHelpCommand ( commandName ) ) {
749
+ const isHelpCommandSyntax = isHelpCommand ( commandName ) ;
750
+
751
+ if ( opts . help || isHelpCommandSyntax ) {
682
752
let isVerbose = false ;
683
753
684
754
if ( opts . help ) {
@@ -694,9 +764,13 @@ class WebpackCLI {
694
764
695
765
this . program . forHelp = true ;
696
766
697
- const optionsForHelp = [ ] . concat ( opts . help && ! isDefault ? [ commandName ] : [ ] ) . concat ( options ) ;
767
+ const optionsForHelp = [ ]
768
+ . concat ( opts . help && ! isDefault ? [ commandName ] : [ ] )
769
+ . concat ( options )
770
+ . concat ( isHelpCommandSyntax && typeof opts . color !== 'undefined' ? [ opts . color ? '--color' : '--no-color' ] : [ ] )
771
+ . concat ( isHelpCommandSyntax && typeof opts . version !== 'undefined' ? [ '--version' ] : [ ] ) ;
698
772
699
- await outputHelp ( optionsForHelp , isVerbose , program ) ;
773
+ await outputHelp ( optionsForHelp , isVerbose , isHelpCommandSyntax , program ) ;
700
774
}
701
775
702
776
if ( opts . version || isVersionCommand ( commandName ) ) {
@@ -710,11 +784,13 @@ class WebpackCLI {
710
784
} else {
711
785
logger . error ( `Unknown command '${ commandName } '` ) ;
712
786
713
- const found = knownCommands . find ( ( commandOptions ) => distance ( commandName , commandOptions . name ) < 3 ) ;
787
+ const found = knownCommands . find ( ( commandOptions ) => distance ( commandName , getCommandName ( commandOptions . name ) ) < 3 ) ;
714
788
715
789
if ( found ) {
716
790
logger . error (
717
- `Did you mean '${ found . name } ' (alias '${ Array . isArray ( found . alias ) ? found . alias . join ( ', ' ) : found . alias } ')?` ,
791
+ `Did you mean '${ getCommandName ( found . name ) } ' (alias '${
792
+ Array . isArray ( found . alias ) ? found . alias . join ( ', ' ) : found . alias
793
+ } ')?`,
718
794
) ;
719
795
}
720
796
0 commit comments