Generating PowerShell module documentation with platyPS

Creating accurate and efficient documentation is paramount in technical writing, especially for PowerShell modules. platyPS, an open-source module, emerged as a solution for generating Markdown-based reference content for PowerShell modules. This article provides a comprehensive guide for using platyPS to create and maintain high-quality reference documentation for your PowerShell module, enhancing the experience for both module authors and users.

What is platyPS

platyPS (pronounced "platypus") started as a tool to convert PowerShell help files into Markdown format. Over time, it evolved into a powerful tool for generating and maintaining PowerShell module documentation directly from the source code and inline documentation. This streamlines the process, ensuring consistency and accuracy while saving valuable time.

A platypus generating PowerShell module documentation

Prerequisites

Before diving into platyPS, ensure you have PowerShell installed. For more information, see Install PowerShell on Windows, Linux, and macOS. Most platyPS commands are cross-platform and work on all platforms supported by PowerShell.

Installation

Install platyPS from the PowerShell Gallery.

1Install-Module -Name platyPS

Define variables

Store the PowerShell module name to document and the locations for the output of the help content in variables. You'll use these variables throughout this article.

1$moduleName = 'MrInspector'
2$markdownPath = '.\docs'
3$mamlPath = '.\en-US'

Optional: If you would like to use the MrInspector module referenced as the example module to document in this article, install it with Install-Module -Name MrInspector.

Generating Markdown files

  1. Import the module to document: Import the module you want to document into your PowerShell session.

    1Import-Module -Name $moduleName
    
  2. Generate initial Markdown help: Run New-MarkdownHelp to create a set of Markdown files for your module. The following parameters are specified in the example below:

    • Module: The name of the module to document.
    • OutputFolder: The folder where you want the generated Markdown files saved.
    • AlphabeticParamsOrder: Sorts parameters in the PARAMETERS section alphabetically except for common parameters and a few other exceptions. This makes finding parameters easier and merging changes less painful.
    • UseFullTypeName: Use full type names for parameter types.
    • WithModulePage: Create a module-level help file.
    • ExcludeDontShow: Include parameters with the DontShow attribute in the generated help because the value is set to true.
    • Encoding: Generate the Markdown files using UTF-8 encoding.
     1$mdHelpParams = @{
     2     Module                = $moduleName
     3     OutputFolder          = $markdownPath
     4     AlphabeticParamsOrder = $true
     5     UseFullTypeName       = $true
     6     WithModulePage        = $true
     7     ExcludeDontShow       = $false
     8     Encoding              = [System.Text.Encoding]::UTF8
     9 }
    10 New-MarkdownHelp @mdHelpParams
    
    1    Directory: /Users/mikefrobbins/docs
    2
    3UnixMode   User Group                LastWriteTime            Size Name
    4--------   ---- -----                -------------            ---- ----
    5-rw-r--r-- mikefrobbins   staff      11/16/2023 05:08         1495 Get-MrSyntax.md
    6-rw-r--r-- mikefrobbins   staff      11/16/2023 05:08          396 MrInspector.md
    
  3. Inspect the files created: platyPS creates one Markdown file for each cmdlet in the module, plus a module-level help file.

  4. Edit the Markdown files: The generated files contain boilerplate text and prompts to fill in details. Edit these files to add parameter descriptions, examples, and other relevant information.

Updating Markdown files

Caution: This step overwrites modifications you've made to the Markdown files.

Use Update-MarkdownHelp to keep your Markdown files in sync as your module evolves. The following example updates all Markdown files in the $markdownPath folder.

1Update-MarkdownHelp -Path $markdownPath
1    Directory: /Users/mikefrobbins/docs
2
3UnixMode   User Group                LastWriteTime            Size Name
4--------   ---- -----                -------------            ---- ----
5-rw-r--r-- mikefrobbins   staff      11/29/2023 06:31         1485 Get-MrSyntax.md

Tip: To avoid overwriting modifications you've made to the Markdown files, consider using New-MarkdownHelp to generate new versions in a different folder instead of using Update-MarkdownHelp, then merge the changes with a comparison tool such as Beyond Compare.

Create about help topics

Use New-MarkdownHelpAbout to create optional about-help topics for your module.

1New-MarkdownAboutHelp -OutputFolder $markdownPath -AboutName $moduleName

Creating external help

After editing the Markdown files, use platyPS to generate external help files in a special XML format known as Microsoft Assistance Markup Language (MAML), which PowerShell can use as cmdlet help.

  1. Generate MAML: Use New-ExternalHelp to create MAML help files.

    1$extHelpParams = @{
    2    Path = $markdownPath
    3    OutputPath = $mamlPath
    4}
    5New-ExternalHelp @extHelpParams
    
    1    Directory: /Users/mikefrobbins/en-US
    2
    3UnixMode   User Group                LastWriteTime            Size Name
    4--------   ---- -----                -------------            ---- ----
    5-rw-r--r-- mikefrobbins   staff      11/29/2023 03:55         1544 about_MrInspector.help.txt
    
  2. Preview the MAML content: Use Get-HelpPreview to test the generated MAML help content and ensure it renders correctly.

    1Get-HelpPreview -Path (Join-Path -Path $mamlPath -ChildPath "$moduleName-help.xml")
    
     1NAME
     2    Get-MrSyntax
     3
     4SYNOPSIS
     5    List PowerShell commands and parameters in the specified PowerShell script.
     6
     7
     8SYNTAX
     9    Get-MrSyntax [[-Path] <String[]>] [-ProgressAction <ActionPreference>] [<CommonParameters>]
    10
    11
    12DESCRIPTION
    13    Get-MrSyntax is a PowerShell function that uses the Abstract Syntax Tree (AST) to determine
    14    the commands and parameters within a PowerShell script.
    15
    16
    17PARAMETERS
    18    -Path <String[]>
    19        Path to one of more PowerShell PS1 or PSM1 script files.
    20
    21        Required?                    false
    22        Position?                    1
    23        Default value                None
    24        Accept pipeline input?       True (ByValue)
    25        Accept wildcard characters?  false
    26
    27    -ProgressAction <ActionPreference>
    28        {{ Fill ProgressAction Description }}
    29
    30        Required?                    false
    31        Position?                    named
    32        Default value                None
    33        Accept pipeline input?       False
    34        Accept wildcard characters?  false
    35
    36    <CommonParameters>
    37        This cmdlet supports the common parameters: Verbose, Debug,
    38        ErrorAction, ErrorVariable, WarningAction, WarningVariable,
    39        OutBuffer, PipelineVariable, and OutVariable. For more information, see
    40        about_CommonParameters (https://go.microsoft.com/fwlink/?LinkID=113216).
    41
    42INPUTS
    43
    44OUTPUTS
    45
    46NOTES
    47
    48
    49        Author:  Mike F. Robbins
    50        Website: https://mikefrobbins.com
    51        Twitter: @mikefrobbins
    52
    53    -------------------------- EXAMPLE 1 --------------------------
    54
    55    Get-MrSyntax -Path C:\Scripts\MyScript.ps1
    56
    57
    58    -------------------------- EXAMPLE 2 --------------------------
    59
    60    Get-ChildItem -Path C:\Scripts\*.ps1 | Get-MrSyntax
    61
    62
    63    -------------------------- EXAMPLE 3 --------------------------
    64
    65    Get-MrSyntax -Path (Get-ChildItem -Path C:\Scripts\*.ps1)
    66
    67
    68
    69RELATED LINKS
    

Tip: If the command scrolls off the screen without you being able to view it, consider piping the output to Out-Host -Paging to view it one page at a time.

1Get-HelpPreview -Path (Join-Path -Path $mamlPath -ChildPath "$moduleName-help.xml") | Out-Host -Paging

Publish the help content

Depending on your requirements, you can publish the help content in several ways.

Ship external help with your module

Include the MAML and about-help topic files with your module to provide integrated help for users of your module. Get-Help looks for module help topic files in language-specific subfolders of your module. The folder structure diagram in the following example shows the location of help topics for my MrInspector PowerShell module.

1<Location in $env:PSModulePath>
2└── MrInspector
3      └── 0.1.0
4         └── en-US
5            ├── MrInspector-help.xml
6            └── about_MrInspector.help.txt

Updatable help

Note: New-ExternalHelpCab is only supported on Windows because it relies on makecab.exe to create CAB files.

  1. Generate files for updatable help: Use New-ExternalHelpCab to create the module help CAB, ZIP, and HelpInfo XML files.

    1$extHelpCabParams = @{
    2    CabFilesFolder = $mamlPath
    3    LandingPagePath = Join-Path -Path $markdownPath -ChildPath "$moduleName.md"
    4    OutputFolder = Join-Path -Path $mamlPath -ChildPath cab
    5}
    6New-ExternalHelpCab @extHelpCabParams
    

Tip: If you encounter an access denied error when running this command, ensure your user has write access to the folder where the command is run from.

  1Version         : 1.0
  2Encoding        : utf-8
  3Standalone      :
  4Value           : version="1.0" encoding="utf-8"
  5InnerText       : version="1.0" encoding="utf-8"
  6Name            : xml
  7LocalName       : xml
  8NodeType        : XmlDeclaration
  9PreviousSibling :
 10NextSibling     :
 11ParentNode      : #document
 12ChildNodes      : {}
 13Attributes      :
 14OwnerDocument   : #document
 15FirstChild      :
 16LastChild       :
 17HasChildNodes   : False
 18NamespaceURI    :
 19Prefix          :
 20IsReadOnly      : False
 21OuterXml        : <?xml version="1.0" encoding="utf-8"?>
 22InnerXml        :
 23SchemaInfo      : System.Xml.Schema.XmlSchemaInfo
 24BaseURI         :
 25PreviousText    :
 26
 27Name            : HelpInfo
 28LocalName       : HelpInfo
 29NamespaceURI    : http://schemas.microsoft.com/powershell/help/2010/05
 30Prefix          :
 31NodeType        : Element
 32ParentNode      : #document
 33OwnerDocument   : #document
 34IsEmpty         : True
 35Attributes      : {}
 36HasAttributes   : False
 37SchemaInfo      : System.Xml.XmlName
 38InnerXml        :
 39InnerText       :
 40NextSibling     :
 41PreviousSibling : xml
 42Value           :
 43ChildNodes      : {}
 44FirstChild      :
 45LastChild       :
 46HasChildNodes   : False
 47IsReadOnly      : False
 48OuterXml        : <HelpInfo xmlns="http://schemas.microsoft.com/powershell/help/2010/05" />
 49BaseURI         :
 50PreviousText    :
 51
 52#text : {{ Update Download Link }}
 53
 54Name            : SupportedUICultures
 55LocalName       : SupportedUICultures
 56NamespaceURI    : http://schemas.microsoft.com/powershell/help/2010/05
 57Prefix          :
 58NodeType        : Element
 59ParentNode      : HelpInfo
 60OwnerDocument   : #document
 61IsEmpty         : True
 62Attributes      : {}
 63HasAttributes   : False
 64SchemaInfo      : System.Xml.XmlName
 65InnerXml        :
 66InnerText       :
 67NextSibling     :
 68PreviousSibling : HelpContentURI
 69Value           :
 70ChildNodes      : {}
 71FirstChild      :
 72LastChild       :
 73HasChildNodes   : False
 74IsReadOnly      : False
 75OuterXml        : <SupportedUICultures xmlns="http://schemas.microsoft.com/powershell/help/2010/05" />
 76BaseURI         :
 77PreviousText    :
 78
 79Name            : UICulture
 80LocalName       : UICulture
 81NamespaceURI    : http://schemas.microsoft.com/powershell/help/2010/05
 82Prefix          :
 83NodeType        : Element
 84ParentNode      : SupportedUICultures
 85OwnerDocument   : #document
 86IsEmpty         : True
 87Attributes      : {}
 88HasAttributes   : False
 89SchemaInfo      : System.Xml.XmlName
 90InnerXml        :
 91InnerText       :
 92NextSibling     :
 93PreviousSibling :
 94Value           :
 95ChildNodes      : {}
 96FirstChild      :
 97LastChild       :
 98HasChildNodes   : False
 99IsReadOnly      : False
100OuterXml        : <UICulture xmlns="http://schemas.microsoft.com/powershell/help/2010/05" />
101BaseURI         :
102PreviousText    :
103
104#text : en-US
105
106#text : {{ Please enter version of help manually (X.X.X.X) format }}
107
108LastWriteTime : 3/10/2024 11:30:46 AM
109Length        : 0
110Name          : MrInspector_f2cb755f-3a8d-47de-974e-70dee6f6355d_HelpInfo.xml
  1. Publish files for updatable help: Publish the CAB/XML files to a web server where your users can access them.

  2. Point the HelpInfoURI property of your module manifest to the folder location of the HelpInfo XML file on the web server. This URL must only point to the folder location, not to the individual file, and it must end with a forward-slash character (/).

Best practices

  • Regular updates: Regularly update your documentation to reflect changes in your module.
  • Version control: Store your documentation in a version control system alongside your module code. This facilitates tracking changes and collaborating with others.
  • Peer review: Have your documentation reviewed by peers for accuracy and clarity.
  • User feedback: Incorporate feedback to improve the usefulness and readability of the documentation.
  • Automation: Automate the generation and updating of documentation as part of the development lifecycle of your module.
  • Consistency: Maintain a consistent style and format across your documentation for a professional look and feel.

Summary

platyPS is an indispensable tool for any PowerShell module author. It automates the generation and maintenance of documentation based on Markdown, ensuring accuracy and consistency and significantly streamlining the process. As PowerShell continues to be an essential tool for system administrators and developers, effective documentation created with tools like platyPS remains crucial for any high-quality PowerShell module.

References

Acknowledgments

Thanks to Sean Wheeler for sharing his insight into this topic and providing valuable feedback that improved the quality of this article.