diff --git a/src/MarkdownReader/CommandHelpMarkdownReader.cs b/src/MarkdownReader/CommandHelpMarkdownReader.cs index 5d85e244..1687989d 100644 --- a/src/MarkdownReader/CommandHelpMarkdownReader.cs +++ b/src/MarkdownReader/CommandHelpMarkdownReader.cs @@ -962,7 +962,8 @@ internal static List 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) { @@ -988,6 +989,50 @@ internal static List GetInputOutput(ParsedMarkdownContent md) return ioList; } + /// + /// Extract the full text content from markdown inline elements, + /// handling square brackets and other special characters correctly. + /// + /// The inline container to extract text from + /// The full text content + private static string ExtractFullTextFromInline(ContainerInline? inline) + { + if (inline == null) return string.Empty; + + StringBuilder sb = new StringBuilder(); + ExtractTextRecursive(inline, sb); + return sb.ToString().Trim(); + } + + /// + /// Recursively extract text from inline elements + /// + /// The inline element to process + /// The StringBuilder to append text to + 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) diff --git a/src/Transform/TransformBase.cs b/src/Transform/TransformBase.cs index e1fa9b78..e560fa92 100644 --- a/src/Transform/TransformBase.cs +++ b/src/Transform/TransformBase.cs @@ -181,7 +181,7 @@ private List GetOutputInfo(CommandInfo commandInfo, dynamic? helpIt string outputName = outputType.Name; if (outputName.EndsWith("[]")) { - outputName = FixUpTypeName(outputName); + outputName = FixUpTypeName(outputName, preserveArrays: true); } if (!outputTypeNames.Contains(outputName)) @@ -801,7 +801,7 @@ protected List 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; @@ -818,7 +818,7 @@ protected List 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 { @@ -826,14 +826,14 @@ protected List GetInputOutputItemsFromHelp(dynamic typesInfo) { 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(); @@ -847,7 +847,8 @@ protected List 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(); @@ -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); } diff --git a/test/Pester/NewMarkdownHelp.Tests.ps1 b/test/Pester/NewMarkdownHelp.Tests.ps1 index cf5bb195..634375e0 100644 --- a/test/Pester/NewMarkdownHelp.Tests.ps1 +++ b/test/Pester/NewMarkdownHelp.Tests.ps1 @@ -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 {