PowerShell / platyPS

Write PowerShell External Help in Markdown
MIT License
778 stars 154 forks source link

Better control on how missing fields are treated in the generation #713

Open awakecoding opened 6 days ago

awakecoding commented 6 days ago

Summary of the new feature / enhancement

I am new to to PlatyPS, and I've been trying to use 1.0.0-Preview1 to generate markdown for the Devolutions.PowerShell module. By default, PlatyPS uses placeholder values that are mean to be manually replaced, like "{{ Fill XYZ }}". The problem is that even if it's good practice to have all the fields (synopsis, inputs/outputs descriptions, related links, etc), this just makes the generated markdown unsuitable for a "good enough" generated static site, one which can still be very useful to navigate through all available cmdlets and parameters.

I don't mind quality checks to list all the missing fields that should be added, but at a bare minimum we should be able to easily control how to treat missing fields: skip them in the generated markdown, or specify the placeholder value to use. Originally, I thought I could work around it by scripting checks for values containing "{{ Fill" to replace them with "", like this:

Import-Module $ModuleName
Get-Command -Module $ModuleName -CommandType Cmdlet | ForEach-Object {
    $CommandHelp = New-CommandHelp $_
    $CommandHelp.RelatedLinks | ForEach-Object { $_.Uri = "/docs/$($_.LinkText)" }
    #$CommandHelp.RelatedLinks += [PSCustomObject]@{ Uri = $ModuleName; LinkText = $ModuleName }
    $CommandHelp.Inputs | Where-Object { $_.Description.Contains("{{ Fill") } | ForEach-Object { $_.Description = "" }
    $CommandHelp.Outputs | Where-Object { $_.Description.Contains("{{ Fill") } | ForEach-Object { $_.Description = "" }
    if ($CommandHelp.Synopsis -and $CommandHelp.Synopsis.Contains('Fill ')) {
        $CommandHelp.Synopsis = ""
    }
    Export-MarkdownCommandHelp -CommandHelp $CommandHelp -OutputFolder $OutputFolder -Force
}

Putting aside the fact that checking for specific values like "{{ Fill" is prone to break if the string changes, I hit another problem: some fields are arrays, where empty arrays of objects result in placeholder text in the output. Since we can't just replace the placeholder value in the object, the only workaround I could find was to post-process the markdown to do a search and replace, which further makes PlatyPS hard to use:

Get-Item "$OutputFolder/$ModuleName/*.md" | ForEach-Object {
    $filePath = $_.FullName
    $content = Get-Content -Path $filePath -Raw
    $content = $content -replace '\{\{Insert list of aliases\}\}', ''
    $content = $content -replace '\{\{ Fill in the related links here \}\}', ''
    Set-Content -Path $filePath -Value $content
}

In the case of related links, if there are none, I'd just like to either skip it, or put the text "None". Post-processing the textual output is very suboptimal and I would like to handle it on the CommandHelp object. I thought of trying to add at least one related link on all cmdlets, but hit another issue: CommandHelp.RelatedLinks is a read-only property, so while I could modify the existing items, I cannot add new items.

My understanding is that the new PlatyPS is designed to make it easier to customize things by scripting modifications to the CommandHelp objects, but from my experience so far (about a day), I've hit several blockers that require hackish workarounds. Is what I'm asking for already supported, but I haven't found the right way to do it, or is it not currently supported? Thanks!

Proposed technical implementation details (optional)

No response

Gijsreyn commented 2 days ago

I was struggling with it as well and there's a way to set internal properties using reflection. Take the following example:

$commandHelpObject = [Microsoft.PowerShell.PlatyPS.Model.CommandHelp]::new()

# Set your properties here that can be set

# To set properties that are gettable only, use reflection. For example, to set the parameters, you can use something like this
$list = [System.Collections.Generic.List[Microsoft.PowerShell.PlatyPS.Model.Parameter]]::new()
$parameter = [Microsoft.PowerShell.PlatyPS.Model.Parameter]::new("MyParameter", "System.String")
$list.Add($parameter)

# Now reflect on it
$property = $commandHelpObject.GetType().GetProperty('Parameters')
$property.SetValue($commandHelpObject, $list, $null)

# Run MarkdownToString()
$commandHelpObject.ToMarkdownString()