Public/New-FunctionMarkdownDoc.ps1
|
Function New-FunctionMarkdownDoc { <# .SYNOPSIS Generates markdown documentation for a PowerShell function script. .EXAMPLE New-FunctionMarkdownDoc -FunctionPath 'C:\Users\ogalbraith\Documents\WindowsPowerShell\Modules\PSModuleDocGen\Public\Get-Parameters.ps1' #> [CmdletBinding()] param( [Parameter(Mandatory=$true, Position=0, HelpMessage="The file path to the PowerShell function file.")] [ValidatePattern('^.+\.ps1$')] [string]$FunctionPath, [ValidatePattern('^.+\.md$')] [Parameter(Mandatory=$false, Position=1, HelpMessage="The file path to output the generated markdown documentation to. If not specified, the markdown file will be created in the same directory as the function file with the same name and a .md extension.")] [string]$OutputPath, [Parameter(Mandatory=$false, Position=2, HelpMessage="Output the generated markdown content to the console instead of writing to a file")] [Switch]$Output, [Parameter(Mandatory=$false, Position=3, HelpMessage="Show the output of the documentation generation process in the console")] [boolean]$ShowOutput = $False ) If ($PSBoundParameters['Debug']) {$DebugPreference = 'Continue'} Add-Type -AssemblyName System.Web $CmdletFile = Get-Item -Path $FunctionPath $CmdletName = $CmdletFile.BaseName $CmdletSynopsis = Get-CmdletSynopsis -CmdletPath $CmdletFile.FullName $CmdletExample = Get-CmdletExample -CmdletPath $CmdletFile.FullName $CmdletParameters = Export-ParameterBlock -CmdletPath $CmdletFile.FullName $ExampleBlock = "" $ParameterBlock = "" ForEach($Example in $CmdletExample.Example) { $ExampleBlockString = " #### Example $($CmdletExample.Example.IndexOf($Example) + 1) ``````powershell $($Example.Replace("__newline__","`n")) `````` " $ExampleBlockString = Format-TabbedString -String $ExampleBlockString $ExampleBlock += $ExampleBlockString } $ExampleBlock = $ExampleBlock.TrimEnd("`n") $Regex = '([\\_^|{])' If($Null -ne $CmdletParameters) { ForEach($Parameter in ($CmdletParameters.ParameterInfo | Sort-Object -Property Name)) { ForEach($OptionSet in $Parameter.Options) { If($null -eq $OptionSet.Mandatory) { $Mandatory = [bool]::FalseString } Else { If($OptionSet.Mandatory -is [string]) { $Mandatory = [bool]::Parse($OptionSet.Mandatory.Trim('$')) } Else { $Mandatory = [bool]$OptionSet.Mandatory } } $ParameterTable = " | | | |-|-| | Type | $($Parameter.Type) | | Mandatory | $Mandatory | " $ParameterTable = Format-TabbedString -String $ParameterTable If($Parameter.DefaultValue) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Default Value found for parameter $($Parameter.Name): $($Parameter.DefaultValue)" $ParameterTable += "| DefaultValue | $($Parameter.DefaultValue) |`r`n" } If($OptionSet.ValidateSet) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] ValidateSet found for parameter $($Parameter.Name): $($OptionSet.ValidateSet -join ', ')" $ParameterTable += "| ValidateSet | $($OptionSet.ValidateSet -join ', ') |`r`n" } If($OptionSet.ValidateRange) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] ValidateRange found for parameter $($Parameter.Name): $($OptionSet.ValidateRange -join ', ')" $ParameterTable += "| ValidateRange | $($OptionSet.ValidateRange -join ', ') |`r`n" } If($OptionSet.ValidatePattern) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] ValidatePattern found for parameter $($Parameter.Name): $($OptionSet.ValidatePattern)" $Result = [System.Text.RegularExpressions.Regex]::new($Regex).Replace($OptionSet.ValidatePattern, '\$1') $ParameterTable += "| ValidatePattern | <pre><code class=`"language-powershell`">$Result</code></pre> |`r`n" } If($OptionSet.ValidateScript) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] ValidateScript found for parameter $($Parameter.Name): $($OptionSet.ValidateScript)" $ValidateScriptString = [System.Web.HttpUtility]::HtmlEncode($OptionSet.ValidateScript.Trim("`r`n")) -replace "`r`n", '<br>' -replace "`n", '<br>' -replace "`t", '	' -replace "'","'" $Result = [System.Text.RegularExpressions.Regex]::new($Regex).Replace($ValidateScriptString, '\$1') $ParameterTable += "| ValidateScript | <pre><code class=`"language-powershell`">$Result</code></pre> |`r`n" } } If($Parameter.Options.ParameterSetName) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] ParameterSetNames found for parameter $($Parameter.Name): $($Parameter.Options.ParameterSetName -join ', ')" $SetNames = ($Parameter.Options.ParameterSetName | Sort-Object -Unique) -join ', ' $ParameterTable += "| ParameterSetNames | $($SetNames.Replace('"', '')) |`r`n" } $ParameterTable = Format-MarkDownTable -Table $ParameterTable $ParameterBlock += "#### -$($Parameter.Name)`n" If($Parameter.Options.HelpMessage) { $ParameterBlock += "`n" $HelpMessageString = $Parameter.Options.HelpMessage | Select-Object -Unique $ParameterBlock += "$($HelpMessageString.Trim('"'))`n`n" } $ParameterBlock += $ParameterTable $ParameterBlock += "`n`n" } } If($PSBoundParameters.Keys -contains "OutputPath") { $FileOutput = $OutputPath } Else { $FileOutput = $FunctionPath.Replace(".ps1",".md") } $FileOutputParent = $FileOutput | Split-Path -Parent # Build markdown source-link path relative to the output markdown directory. $OutputDirectory = [System.IO.Path]::GetFullPath($FileOutputParent) $FunctionFullPath = [System.IO.Path]::GetFullPath($CmdletFile.FullName) $OutputDirectoryUri = [System.Uri]::new(($OutputDirectory.TrimEnd('\') + '\')) $FunctionUri = [System.Uri]::new($FunctionFullPath) $MarkdownContent = " ## $CmdletName ### Description <<<synopsis>>> --- `````` <<<parameters>>> `````` --- ### Source Code <<<source_code_link>>> ### Examples <<<examples>>> --- ### Parameters <<<parameter_tables>>> " $MarkdownContent = Format-TabbedString -String $MarkdownContent $MarkdownContent = $MarkdownContent -creplace '<<<synopsis>>>', $($CmdletSynopsis.Synopsis) $MarkdownContent = $MarkdownContent -creplace '<<<source_code_link>>>', "[$($CmdletName).ps1]($([System.Uri]::UnescapeDataString($OutputDirectoryUri.MakeRelativeUri($FunctionUri).ToString())))" If($Null -ne $CmdletParameters) { $MarkdownContent = $MarkdownContent -creplace '<<<parameters>>>', $($CmdletParameters.Block) $MarkdownContent = $MarkdownContent -creplace '<<<parameter_tables>>>', "$($ParameterBlock)" } Else { # Remove parameter blocks from markdown # $MarkdownContent = $MarkdownContent -replace "\s<<<parameters>>>\s*","" -replace "``````\s*", "" -replace "---\s*", "" $MarkdownContent = $MarkdownContent -replace "---\s+``````\s+<<<parameters>>>\s+``````\s+---\s+","" $MarkdownContent = $MarkdownContent -replace "---\s*#+ Parameters\s*<<<parameter_tables>>>\s*", "" } $MarkdownContent = $MarkdownContent -creplace '<<<examples>>>', "$($ExampleBlock)" $MarkdownContent = $MarkdownContent.Trim() $Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False If($Output -eq $false) { If((Test-Path -Path $FileOutputParent) -eq $false) { New-Item -Path $FileOutputParent -ItemType Directory | Out-Null } [System.IO.File]::WriteAllLines($FileOutput, $MarkdownContent, $Utf8NoBomEncoding) If($ShowOutput -eq $True) { Return Get-Item -Path $FileOutput } } Else { Return $MarkdownContent } } |