diff --git a/apps/spfx-cli/src/cli/actions/CreateAction.ts b/apps/spfx-cli/src/cli/actions/CreateAction.ts index 8da46af7..f25b79cf 100644 --- a/apps/spfx-cli/src/cli/actions/CreateAction.ts +++ b/apps/spfx-cli/src/cli/actions/CreateAction.ts @@ -48,7 +48,7 @@ const ScaffoldProfileSchema: z.ZodType = z.object({ export class CreateAction extends SPFxActionBase { private readonly _targetDirParameter: CommandLineStringParameter; private readonly _templateParameter: IRequiredCommandLineStringParameter; - private readonly _libraryNameParameter: IRequiredCommandLineStringParameter; + private readonly _libraryNameParameter: CommandLineStringParameter; private readonly _componentNameParameter: IRequiredCommandLineStringParameter; private readonly _componentAliasParameter: CommandLineStringParameter; private readonly _componentDescriptionParameter: CommandLineStringParameter; @@ -83,8 +83,8 @@ export class CreateAction extends SPFxActionBase { this._libraryNameParameter = this.defineStringParameter({ parameterLongName: '--library-name', argumentName: 'LIBRARY_NAME', - description: 'The library name for the component', - required: true + description: 'The library name for the component. Defaults to the solution name if not specified.', + required: false }); this._componentNameParameter = this.defineStringParameter({ @@ -204,7 +204,7 @@ export class CreateAction extends SPFxActionBase { const builtInContext: ISPFxBuiltInContext = buildBuiltInContext( { componentName, - libraryName: this._libraryNameParameter.value, + libraryName: this._libraryNameParameter.value || solutionName, spfxVersion: template.spfxVersion, solutionName: rawSolutionName || undefined, componentAlias: this._componentAliasParameter.value?.trim() || undefined, @@ -269,6 +269,15 @@ export class CreateAction extends SPFxActionBase { throw error; } } + + protected override getExamples(): string[] { + return [ + 'Create a new React web part. Scaffolds into a subfolder named after the solution:\n spfx create --template webpart-react --component-name "HelloWorld" --solution-name "helloworld" --component-description "A Hello World web part"', + 'Create an extension. Skips package install with --package-manager none:\n spfx create --template extension-field --component-name "ColorField" --package-manager none', + 'Create a web part from a local template source:\n spfx create --template webpart-react --component-name "MyWebPart" --library-name "mywebpart" --solution-name "mywebpart" --local-source ./my-templates', + 'Create a web part with a specific SPFx version:\n spfx create --template webpart-react --component-name "MyWP" --component-description "Description" --spfx-version 1.22 --library-name "mywp" --solution-name "mywp"' + ]; + } } /** diff --git a/apps/spfx-cli/src/cli/actions/SPFxActionBase.ts b/apps/spfx-cli/src/cli/actions/SPFxActionBase.ts index d6ca0250..6fb9dddb 100644 --- a/apps/spfx-cli/src/cli/actions/SPFxActionBase.ts +++ b/apps/spfx-cli/src/cli/actions/SPFxActionBase.ts @@ -166,4 +166,37 @@ export abstract class SPFxActionBase extends CommandLineAction { } } } + + /** + * Returns usage examples for this action. Each string is a self-contained example + * with the command invocation and a brief description of what it does. + * Override in subclasses to provide examples. The default returns an empty array. + */ + protected getExamples(): string[] { + return []; + } + + /** + * Overrides the base help text rendering to append a formatted EXAMPLES section + * when examples are defined. + */ + public override renderHelpText(): string { + const base: string = super.renderHelpText(); + const examples: string[] = this.getExamples(); + if (examples.length === 0) { + return base; + } + + // Append examples after the last line of base help + // Normalize Windows CRLF to LF before splitting so every line is clean + const lines: string[] = base.replace(/\r\n/g, '\n').split('\n'); + lines.push(''); + lines.push('EXAMPLES'); + for (const example of examples) { + lines.push(''); + lines.push(` ${example}`); + } + lines.push(''); + return lines.join('\n'); + } } diff --git a/apps/spfx-cli/src/cli/test/__snapshots__/CommandLineHelp.test.ts.snap b/apps/spfx-cli/src/cli/test/__snapshots__/CommandLineHelp.test.ts.snap index b7be4dfb..2bc50195 100644 --- a/apps/spfx-cli/src/cli/test/__snapshots__/CommandLineHelp.test.ts.snap +++ b/apps/spfx-cli/src/cli/test/__snapshots__/CommandLineHelp.test.ts.snap @@ -56,7 +56,22 @@ Optional arguments: Package manager to use for dependency installation after scaffolding. Use \\"none\\" to skip installation. The default value is \\"none\\". -" + + +EXAMPLES + + Create a new React web part. Scaffolds into a subfolder named after the solution: + spfx create --template webpart-react --component-name \"HelloWorld\" --solution-name \"helloworld\" --component-description \"A Hello World web part\" + + Create an extension. Skips package install with --package-manager none: + spfx create --template extension-field --component-name \"ColorField\" --package-manager none + + Create a web part from a local template source: + spfx create --template webpart-react --component-name \"MyWebPart\" --library-name \"mywebpart\" --solution-name \"mywebpart\" --local-source ./my-templates + + Create a web part with a specific SPFx version: + spfx create --template webpart-react --component-name \"MyWP\" --component-description \"Description\" --spfx-version 1.22 --library-name \"mywp\" --solution-name \"mywp\" +\" `; exports[`CommandLineHelp prints the help: global help 1`] = ` diff --git a/common/changes/@microsoft/spfx-cli/help-examples_2026-07-13.json b/common/changes/@microsoft/spfx-cli/help-examples_2026-07-13.json new file mode 100644 index 00000000..a0a328ef --- /dev/null +++ b/common/changes/@microsoft/spfx-cli/help-examples_2026-07-13.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@microsoft/spfx-cli", + "comment": "", + "type": "none" + } + ], + "packageName": "@microsoft/spfx-cli" +}