Private/Bases/Doc.ps1
function Get-FunctionDoc{ <# .DESCRIPTION Get function docs from a script file. Return a hashtable with function names as keys and function docs as values. .INPUTS String. .OUTPUTS Hashtable. #> [CmdletBinding()] [OutputType([hashtable])] param( [Parameter(Mandatory)] [string]$Path ) if (-not (Test-Path -Path $Path -PathType Leaf)){ throw "Path '$Path' does not exist or is not a file." } if (-not ($Path.EndsWith('.ps1') -or $Path.EndsWith('.psm1'))){ throw "Path '$Path' is not a PowerShell script file." } $script_content = Get-Content -Path $Path -Raw $function_bloks = $script_content | Select-String -Pattern '(?sm)^\s*function .*?^\}' -AllMatches $function_name_with_docs = @{} foreach ($match in $function_bloks.Matches) { $block = $match.Value $function_name = ($block | Select-String -Pattern 'function\s+([A-Za-z0-9_\-]+)').Matches.Groups[1].Value $comment_matched = $block | Select-String -Pattern '(?s)<#(.*?)#>' if ($comment_matched.Count -ne 0){ $function_comment = $comment_matched.Matches.Groups[1].Value } else{ $function_comment = '' } $function_name_with_docs[$function_name] = $function_comment } return $function_name_with_docs } function Get-ClassDoc{ <# .DESCRIPTION Get class docs from a script file. Return a hashtable with class names as keys and class docs as values. .INPUTS String. .OUTPUTS Hashtable. #> [CmdletBinding()] [OutputType([hashtable])] param( [Parameter(Mandatory)] [string]$Path ) if (-not (Test-Path -Path $Path -PathType Leaf)){ throw "Path '$Path' does not exist or is not a file." } if (-not ($Path.EndsWith('.ps1') -or $Path.EndsWith('.psm1'))){ throw "Path '$Path' is not a PowerShell script file." } $script_content = Get-Content -Path $Path -Raw $class_bloks = $script_content | Select-String -Pattern '(?sm)^\s*class .*?^\}' -AllMatches $class_name_with_docs = @{} foreach ($match in $class_bloks.Matches) { $block = $match.Value $class_name = ($block | Select-String -Pattern 'class\s+([A-Za-z0-9_]+)').Matches.Groups[1].Value $comment_matched = $block | Select-String -Pattern '(?s)<#(.*?)#>' if ($comment_matched.Count -ne 0){ $class_comment = $comment_matched.Matches.Groups[1].Value } else{ $class_comment = '' } $class_name_with_docs[$class_name] = $class_comment } return $class_name_with_docs } function Format-Doc2Markdown{ <# .DESCRIPTION Convert a function doc to markdown string with a fixed format. .NOTES The formatted markdown string is like this: ```markdown - Synopsis xxx - Description xxx - Parameters `$Aa` xxx - Parameters `$Bb` xxx ``` .INPUTS String. .OUTPUTS String. #> [CmdletBinding()] [OutputType([string])] param( [Parameter(Mandatory)] [string]$DocString ) $function_comment = $null if ($DocString){ $comment_lines = $DocString -split '\r?\n' $block = @() foreach ($line in $comment_lines) { $line = $line.TrimStart() if ($line -match '^(\.)(\w+)[ ]*(\w*)') { # Function-Name -> ### Function-Name # .DESCRIPTION -> - Description # .PARAMETER xxx -> - Parameter `xxx` $title = '- **'+$Matches[2].Substring(0,1).ToUpper() + $Matches[2].Substring(1).ToLower()+'**' if ($Matches[3]) { $title += " ```$$($Matches[3])``" } $block += $title $block += '' } else { $block += ' '*4+$line } } $function_comment = $block -join "`r`n" } return $function_comment } function Get-SortedNameWithDocFromScript{ <# .DESCRIPTION Get sorted function names with docs from a script file or script files. Return a hashtable enumerator with sorted function names as keys(names) and function docs as values. .PARAMETER Path The path of a script file or script files. .PARAMETER DocType The type of docs, 'Function' or 'Class'. .INPUTS String[]. String. .OUTPUTS System.Collections.DictionaryEntry. .LINK [Why both `Name` and `Key` are available?](https://stackoverflow.com/a/77083569/17357963) [Types.ps1xml](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_types.ps1xml?view=powershell-7.3) #> [OutputType([System.Collections.DictionaryEntry])] param( [Parameter(Mandatory)] [string[]]$Path, [Parameter(Mandatory)] [ValidateSet('Function','Class')] [string]$DocType ) $name_with_docs = @{} foreach ($item in $Path) { if ($DocType -eq 'Function'){ $name_with_docs += Get-FunctionDoc -Path $item }else{ $name_with_docs += Get-ClassDoc -Path $item } } $sorted_name_with_docs = $name_with_docs.GetEnumerator() | Sort-Object -Property Name return $sorted_name_with_docs } |