Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 46 additions & 1 deletion src/MarkdownReader/CommandHelpMarkdownReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -962,7 +962,8 @@ internal static List<InputOutput> GetInputOutput(ParsedMarkdownContent md)
{
if (md.GetCurrent() is HeadingBlock inputOutputHeader)
{
string inputType = inputOutputHeader?.Inline?.FirstChild?.ToString() ?? string.Empty;
// Extract full text content from all inline elements to handle arrays and other complex types
string inputType = ExtractFullTextFromInline(inputOutputHeader?.Inline);
md.Take();
if (md.GetCurrent() is ParagraphBlock pBlock)
{
Expand All @@ -988,6 +989,50 @@ internal static List<InputOutput> GetInputOutput(ParsedMarkdownContent md)
return ioList;
}

/// <summary>
/// Extract the full text content from markdown inline elements,
/// handling square brackets and other special characters correctly.
/// </summary>
/// <param name="inline">The inline container to extract text from</param>
/// <returns>The full text content</returns>
private static string ExtractFullTextFromInline(ContainerInline? inline)
{
if (inline == null) return string.Empty;

StringBuilder sb = new StringBuilder();
ExtractTextRecursive(inline, sb);
return sb.ToString().Trim();
}

/// <summary>
/// Recursively extract text from inline elements
/// </summary>
/// <param name="inline">The inline element to process</param>
/// <param name="sb">The StringBuilder to append text to</param>
private static void ExtractTextRecursive(Inline inline, StringBuilder sb)
{
switch (inline)
{
case LiteralInline literal:
sb.Append(literal.Content.ToString());
break;
case ContainerInline container:
foreach (var child in container)
{
ExtractTextRecursive(child, sb);
}
break;
default:
// For other inline types, try to get their text representation
var text = inline.ToString();
if (!string.IsNullOrEmpty(text))
{
sb.Append(text);
}
break;
}
}

internal static string GetParameterSetName(HeadingBlock parameterSetBlock)
{
if (parameterSetBlock is null)
Expand Down
15 changes: 8 additions & 7 deletions src/Transform/TransformBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ private List<InputOutput> GetOutputInfo(CommandInfo commandInfo, dynamic? helpIt
string outputName = outputType.Name;
if (outputName.EndsWith("[]"))
{
outputName = FixUpTypeName(outputName);
outputName = FixUpTypeName(outputName, preserveArrays: true);
}

if (!outputTypeNames.Contains(outputName))
Expand Down Expand Up @@ -801,7 +801,7 @@ protected List<InputOutput> GetInputOutputItemsFromHelp(dynamic typesInfo)
{
foreach (dynamic ioType in typesInfo)
{
string typeName = FixUpTypeName(ioType.type.name?.Split()?[0] ?? string.Empty);
string typeName = FixUpTypeName(ioType.type.name?.Split()?[0] ?? string.Empty, preserveArrays: true);
if (! string.IsNullOrEmpty(typeName) && string.Compare(typeName, "None", true) != 0)
{
string description = GetStringFromDescriptionArray(ioType.description)?.Trim() ?? string.Empty;
Expand All @@ -818,22 +818,22 @@ protected List<InputOutput> GetInputOutputItemsFromHelp(dynamic typesInfo)
// these are really multiple entries, so split them here.
if (name.IndexOf("\n") == -1 && string.Compare(name, "None", true) != 0)
{
itemList.Add(new InputOutput(FixUpTypeName(name), Constants.FillInDescription));
itemList.Add(new InputOutput(FixUpTypeName(name, preserveArrays: true), Constants.FillInDescription));
}
else
{
foreach(var tName in name.Replace("\\r","").Split('\n'))
{
if (string.Compare(tName, "None", true) != 0)
{
itemList.Add(new InputOutput(FixUpTypeName(tName), Constants.FillInDescription));
itemList.Add(new InputOutput(FixUpTypeName(tName, preserveArrays: true), Constants.FillInDescription));
}
}
}
}
else
{
string typeName = FixUpTypeName(ioTypes.type.name.ToString());
string typeName = FixUpTypeName(ioTypes.type.name.ToString(), preserveArrays: true);
if (! string.IsNullOrEmpty(typeName) && string.Compare(typeName, "None", true) != 0)
{
string description = GetStringFromDescriptionArray(ioTypes.description).Trim();
Expand All @@ -847,7 +847,8 @@ protected List<InputOutput> GetInputOutputItemsFromHelp(dynamic typesInfo)

// We have to remove carriage returns that might be present from help
// We also will remove trailing [] because we should generally return singletons
private string FixUpTypeName(string typename)
// For input/output types, preserve array notation as it's semantically important
private string FixUpTypeName(string typename, bool preserveArrays = false)
{
// If the type is a generic type, we need to remove the backtick and the number.
string fixedString = typename.Replace("System.Nullable`1[[", string.Empty).Trim();
Expand All @@ -857,7 +858,7 @@ private string FixUpTypeName(string typename)
fixedString = fixedString.Substring(0, commaIndex).Trim();
}

if (fixedString.EndsWith("[]"))
if (!preserveArrays && fixedString.EndsWith("[]"))
{
fixedString = fixedString.Remove(fixedString.Length - 2);
}
Expand Down
38 changes: 38 additions & 0 deletions test/Pester/NewMarkdownHelp.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,44 @@ Write-Host 'Hello World!'
}
}

Context 'Array type handling in pipeline parameters' {
function global:Test-ArrayPipelineFunction
{
[CmdletBinding()]
param(
[Parameter(Mandatory, ValueFromPipeline)]
[string[]]$ComputerName,

[Parameter()]
[int[]]$Numbers
)
}

BeforeAll {
$file = New-MarkdownCommandHelp -Command (Get-Command Test-ArrayPipelineFunction) -OutputFolder "$TestDrive/arrayTest" -Force
$content = Import-MarkdownCommandHelp $file
}

It 'should generate correct input type for string array parameter' {
$content.Inputs.Count | Should -Be 1
$content.Inputs[0].Typename | Should -Be 'System.String[]'
}

It 'should not duplicate array and element types in inputs' {
$inputTypes = $content.Inputs | ForEach-Object { $_.Typename }
$inputTypes | Should -Not -Contain 'System.String'
$inputTypes | Should -Contain 'System.String[]'
}

It 'should preserve array notation in markdown and parsing roundtrip' {
Update-MarkdownCommandHelp -Path $file -NoBackup
$updatedContent = Import-MarkdownCommandHelp $file

$updatedContent.Inputs.Count | Should -Be 1
$updatedContent.Inputs[0].Typename | Should -Be 'System.String[]'
}
}

Context 'Generated markdown features: no comment-based help' {
function global:Test-PlatyPSFunction
{
Expand Down