Public/Update-ModuleDocumentation.ps1

Function Update-ModuleDocumentation
    {
        <#
        .SYNOPSIS
        This function updates the documentation for a specified PowerShell module. It can use either the module's path or name to locate the module and generate the documentation.
        .EXAMPLE
        # Update documentation for a module using the module path
        Update-ModuleDocumentation -Path "C:\Users\ogalbraith\Documents\WindowsPowerShell\Modules\PSModuleDocGen"
        .EXAMPLE
        # Update documentation for a module using the module name
        Update-ModuleDocumentation -Name "PSModuleDocGen"
        #>


        [CmdletBinding(DefaultParameterSetName="ModuleName")]
        param(
            [Parameter(Mandatory=$true, ParameterSetName="ModulePath", Position=0, HelpMessage="The file path to the module to document")]
            [string]$Path,
            [Parameter(Mandatory=$false, Position=1, HelpMessage="The description of the module")]
            [string]$Description,
            [Parameter(Mandatory=$false, Position=2, HelpMessage="Show the output of the documentation generation process in the console")]
            [boolean]$ShowOutput = $False
        )

        DynamicParam
            {
                $DynamicParameterDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new()

                $NewDynamicParams = @{
                    DynamicParameterDictionary = $DynamicParameterDictionary
                }

                $AvailableModules = Get-Module | Select-Object -ExpandProperty Name

                $ParamList = @(
                    @{
                        ParameterName    = 'Name'
                        ParameterType    = ([string])
                        Mandatory        = $true
                        ValidateSet      = [array]$AvailableModules
                        HelpMessage      = "The name of the module to document. This will be used to find the module path. This parameter is not required if the ModulePath parameter is used."
                        Position         = 0
                        ParameterSetName = 'ModuleName'
                    }
                )

                ForEach($Param in $ParamList)
                    {
                        Add-DynamicParameter @NewDynamicParams @Param
                    }
                Return $DynamicParameterDictionary
            }

        Begin
            {
                If($PSCmdlet.ParameterSetName -eq "ModuleName")
                    {
                        $Name = $DynamicParameterDictionary['Name'].Value
                        $ModuleInfo = Get-Module -Name $Name | Select-Object -First 1
                        If($null -eq $ModuleInfo)
                            {
                                Write-Error "Unable to find module with name '$Name'"
                                Break
                            }
                        $Path = $ModuleInfo.ModuleBase
                    }
                ElseIf($PSCmdlet.ParameterSetName -eq "ModulePath")
                    {
                        $Path = $Path.TrimEnd('\').TrimEnd('/')
                    }
            }

        Process
            {
                If([String]::IsNullOrEmpty($Path))
                    {
                        Write-Error "Module path is required. Please provide a valid path to the module."
                        Break
                    }

                $ItemInfo = Get-Item -Path $Path
                If($ItemInfo.PSIsContainer -eq $true)
                    {
                        $ModuleManifestPath = Get-ChildItem -Path $Path -Filter "*.psd1" | Select-Object -ExpandProperty Fullname
                    }
                ElseIf(($ItemInfo.PSIsContainer -eq $false) -and ($Path -notlike "*.psm1"))
                    {
                        Write-Error "Unable to find correct module file"
                        Break
                    }

                $ModuleName = $Path | Split-Path -Leaf

                If($PSBoundParameters.Keys -notcontains 'Description')
                    {
                        $ManifestInfo = Import-PowerShellDataFile -Path $ModuleManifestPath
                        $Description = $ManifestInfo.Description
                        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Module description pulled from manifest file"
                        Write-Verbose "[$($MyInvocation.MyCommand.Name)] $Description"
                    }

                $DocsPath = 'docs/cmdlets'

                $AbsolutePath = (Get-Item -Path $Path).FullName
                $FileOutput = "$AbsolutePath/README.md"

                $PublicCmdletFiles = Get-ChildItem -Path "$AbsolutePath/Public" -Recurse -Filter "*.ps1" | Sort-Object -Property Name
                $PrivateCmdletFiles = Get-ChildItem -Path "$AbsolutePath/Private" -Recurse -Filter "*.ps1" | Sort-Object -Property Name

                $MarkdownContent = ""
                $MarkdownContent += "### $ModuleName`n"
                $MarkdownContent += "`n"
                $MarkdownContent += "##### Description`n"
                $MarkdownContent += "`n"
                $MarkdownContent += "$Description"
                $MarkdownContent += "`n"
                $MarkdownContent += "*****`n"
                $MarkdownContent += "`n"
                $MarkdownContent += "##### Available Cmdlets`n"

                ForEach($Cmdlet in $PublicCmdletFiles)
                    {
                        $OutputFile = $Cmdlet.Fullname -replace "Public(/.*)?/$($Cmdlet.Name)", "$DocsPath/$($Cmdlet.Name.Replace('.ps1','.md'))"

                        New-FunctionMarkdownDoc -FunctionPath $Cmdlet.FullName -OutputPath $OutputFile -ShowOutput $ShowOutput -ErrorAction Stop

                        $MarkdownContent += "+ [$($Cmdlet.BaseName)]($DocsPath/$($Cmdlet.Name.Replace('.ps1','.md')))`n"
                    }

                If($PrivateCmdletFiles.Count -gt 0)
                    {
                        $MarkdownContent += "`n"
                        $MarkdownContent += "##### Private Functions`n"

                        ForEach($Cmdlet in $PrivateCmdletFiles)
                            {
                                $OutputFile = $Cmdlet.Fullname -replace "Private(/.*)?/$($Cmdlet.Name)", "$DocsPath/Private/$($Cmdlet.Name.Replace('.ps1','.md'))"

                                New-FunctionMarkdownDoc -FunctionPath $Cmdlet.FullName -OutputPath $OutputFile -ShowOutput $ShowOutput -ErrorAction Stop

                                $MarkdownContent += "+ [$($Cmdlet.BaseName)]($DocsPath/Private/$($Cmdlet.Name.Replace('.ps1','.md')))`n"
                            }
                    }

                $MarkdownContent += "`n"
                $MarkdownContent += "*****`n"
                $MarkdownContent += "`n"
                $MarkdownContent += "##### Usage`n"
                $MarkdownContent += "To install and use this module, use the following code`n"
                $MarkdownContent += "`n"
                $MarkdownContent += "``````powershell`n"
                $MarkdownContent += "PS C:\> Install-Module -Name $ModuleName`n"
                $MarkdownContent += "`n"
                $MarkdownContent += "PS C:\> Import-Module -Name $ModuleName`n"
                $MarkdownContent += "``````"


                $Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
                [System.IO.File]::WriteAllLines($FileOutput, $MarkdownContent, $Utf8NoBomEncoding)
            }
    }