diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0467a2da..0b4f7aa8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,7 @@ CHANGELOG
## Not released
* Clean up trailing whitespace during markdown generation [#225](https://github.com/PowerShell/platyPS/issues/225)
+* Preserve line breaks after headers when Update-MarkdownHelp is used [#319](https://github.com/PowerShell/platyPS/issues/319)
## 0.8.3
diff --git a/src/Markdown.MAML/Markdown.MAML.csproj b/src/Markdown.MAML/Markdown.MAML.csproj
index 2abdec2e..3e7f9e72 100644
--- a/src/Markdown.MAML/Markdown.MAML.csproj
+++ b/src/Markdown.MAML/Markdown.MAML.csproj
@@ -61,6 +61,8 @@
+
+
diff --git a/src/Markdown.MAML/Model/MAML/MamlCommand.cs b/src/Markdown.MAML/Model/MAML/MamlCommand.cs
index fec99500..3cec6a68 100644
--- a/src/Markdown.MAML/Model/MAML/MamlCommand.cs
+++ b/src/Markdown.MAML/Model/MAML/MamlCommand.cs
@@ -6,9 +6,12 @@ namespace Markdown.MAML.Model.MAML
public class MamlCommand
{
public SourceExtent Extent { get; set; }
+
public string Name { get; set; }
- public string Synopsis { get; set; }
- public string Description { get; set; }
+
+ public SectionBody Synopsis { get; set; }
+
+ public SectionBody Description { get; set; }
public List Inputs
{
@@ -25,7 +28,7 @@ public List Parameters
get { return _parameters; }
}
- public string Notes { get; set; }
+ public SectionBody Notes { get; set; }
public bool IsWorkflow { get; set; }
diff --git a/src/Markdown.MAML/Model/MAML/MamlExample.cs b/src/Markdown.MAML/Model/MAML/MamlExample.cs
index 2e3f1af4..22df8c73 100644
--- a/src/Markdown.MAML/Model/MAML/MamlExample.cs
+++ b/src/Markdown.MAML/Model/MAML/MamlExample.cs
@@ -1,4 +1,5 @@
-using System;
+using Markdown.MAML.Model.Markdown;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -12,5 +13,10 @@ public class MamlExample
public string Code { get; set; }
public string Remarks { get; set; }
public string Introduction { get; set; }
+
+ ///
+ /// Additional options that determine how the section will be formated when rendering markdown.
+ ///
+ public SectionFormatOption FormatOption { get; set; }
}
}
diff --git a/src/Markdown.MAML/Model/MAML/MamlInputOutput.cs b/src/Markdown.MAML/Model/MAML/MamlInputOutput.cs
index 96a0906c..53fb7aca 100644
--- a/src/Markdown.MAML/Model/MAML/MamlInputOutput.cs
+++ b/src/Markdown.MAML/Model/MAML/MamlInputOutput.cs
@@ -1,4 +1,5 @@
-using System;
+using Markdown.MAML.Model.Markdown;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -14,6 +15,11 @@ public class MamlInputOutput : IEquatable
public string TypeName { get; set; }
public string Description { get; set; }
+ ///
+ /// Additional options that determine how the section will be formated when rendering markdown.
+ ///
+ public SectionFormatOption FormatOption { get; set; }
+
bool IEquatable.Equals(MamlInputOutput other)
{
if (!StringComparer.OrdinalIgnoreCase.Equals(other.TypeName, this.TypeName))
diff --git a/src/Markdown.MAML/Model/MAML/MamlParameter.cs b/src/Markdown.MAML/Model/MAML/MamlParameter.cs
index 6de90f6b..f1e594c4 100644
--- a/src/Markdown.MAML/Model/MAML/MamlParameter.cs
+++ b/src/Markdown.MAML/Model/MAML/MamlParameter.cs
@@ -9,6 +9,11 @@ public class MamlParameter : ICloneable
{
public SourceExtent Extent { get; set; }
+ ///
+ /// Additional options that determine how the section will be formated when rendering markdown.
+ ///
+ public SectionFormatOption FormatOption { get; set; }
+
public string Type { get; set; }
public string FullType { get; set; }
diff --git a/src/Markdown.MAML/Model/Markdown/HeadingNode.cs b/src/Markdown.MAML/Model/Markdown/HeadingNode.cs
index 5a98c935..dc62af74 100644
--- a/src/Markdown.MAML/Model/Markdown/HeadingNode.cs
+++ b/src/Markdown.MAML/Model/Markdown/HeadingNode.cs
@@ -9,10 +9,16 @@ public override MarkdownNodeType NodeType
public int HeadingLevel { get; private set; }
- public HeadingNode(string headingText, int headingLevel, SourceExtent sourceExtent)
+ ///
+ /// Additional options that determine how the section will be formated when rendering markdown. This options will be passed on to MAML models when they are generated.
+ ///
+ public SectionFormatOption FormatOption { get; private set; }
+
+ public HeadingNode(string headingText, int headingLevel, SourceExtent sourceExtent, SectionFormatOption formatOption)
: base(headingText, sourceExtent)
{
this.HeadingLevel = headingLevel;
+ this.FormatOption = formatOption;
}
}
}
diff --git a/src/Markdown.MAML/Model/Markdown/SectionBody.cs b/src/Markdown.MAML/Model/Markdown/SectionBody.cs
new file mode 100644
index 00000000..aaee004b
--- /dev/null
+++ b/src/Markdown.MAML/Model/Markdown/SectionBody.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Markdown.MAML.Model.Markdown
+{
+ ///
+ /// A section of text with formatting options.
+ ///
+ public sealed class SectionBody
+ {
+ public SectionBody(string text, SectionFormatOption formatOption)
+ {
+ Text = text;
+ FormatOption = formatOption;
+ }
+
+ public SectionBody(string text)
+ : this(text, SectionFormatOption.None)
+ { }
+
+ ///
+ /// The text of the section body.
+ ///
+ public string Text { get; private set; }
+
+ ///
+ /// Additional options that determine how the section will be formated when rendering markdown.
+ ///
+ public SectionFormatOption FormatOption { get; private set; }
+
+ public override string ToString()
+ {
+ return Text;
+ }
+ }
+}
diff --git a/src/Markdown.MAML/Model/Markdown/SectionFormatOption.cs b/src/Markdown.MAML/Model/Markdown/SectionFormatOption.cs
new file mode 100644
index 00000000..643a9696
--- /dev/null
+++ b/src/Markdown.MAML/Model/Markdown/SectionFormatOption.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Markdown.MAML.Model.Markdown
+{
+ ///
+ /// Define options that determine how sections will be formated when rendering markdown.
+ ///
+ [Flags()]
+ public enum SectionFormatOption : byte
+ {
+ None = 0,
+
+ ///
+ /// A line break should be added after the section header.
+ ///
+ LineBreakAfterHeader = 1
+ }
+}
diff --git a/src/Markdown.MAML/Parser/MarkdownParser.cs b/src/Markdown.MAML/Parser/MarkdownParser.cs
index 6c20c603..8bd1f53b 100644
--- a/src/Markdown.MAML/Parser/MarkdownParser.cs
+++ b/src/Markdown.MAML/Parser/MarkdownParser.cs
@@ -307,7 +307,10 @@ private void CreateHashHeader(Match regexMatch, SourceExtent sourceExtent)
new HeadingNode(
regexMatch.Groups[2].Value,
regexMatch.Groups[1].Value.Length,
- sourceExtent));
+ sourceExtent,
+
+ // Detect if a line break after the header exists. Mutiple line breaks will be reduced to one.
+ (regexMatch.Groups[3].Captures.Count > 1) ? SectionFormatOption.LineBreakAfterHeader : SectionFormatOption.None));
}
private void CreateHashHeader2(Match regexMatch, SourceExtent sourceExtent)
@@ -318,7 +321,10 @@ private void CreateHashHeader2(Match regexMatch, SourceExtent sourceExtent)
new HeadingNode(
regexMatch.Groups[3].Value,
regexMatch.Groups[2].Value.Length,
- sourceExtent));
+ sourceExtent,
+
+ // Detect if a line break after the header exists. Mutiple line breaks will be reduced to one.
+ (regexMatch.Groups[4].Captures.Count > 1) ? SectionFormatOption.LineBreakAfterHeader : SectionFormatOption.None));
}
private void CreateUnderlineHeader(Match regexMatch, SourceExtent sourceExtent)
@@ -333,7 +339,10 @@ private void CreateUnderlineHeader(Match regexMatch, SourceExtent sourceExtent)
new HeadingNode(
regexMatch.Groups[1].Value,
headerLevel,
- sourceExtent));
+ sourceExtent,
+
+ // Detect if a line break after the header exists. Mutiple line breaks will be reduced to one.
+ (regexMatch.Groups[3].Captures.Count > 1) ? SectionFormatOption.LineBreakAfterHeader : SectionFormatOption.None));
}
private void CreateTickCodeBlock(Match regexMatch, SourceExtent sourceExtent)
diff --git a/src/Markdown.MAML/Renderer/MamlRenderer.cs b/src/Markdown.MAML/Renderer/MamlRenderer.cs
index 6c070843..e2cc98ab 100644
--- a/src/Markdown.MAML/Renderer/MamlRenderer.cs
+++ b/src/Markdown.MAML/Renderer/MamlRenderer.cs
@@ -64,14 +64,14 @@ private static XElement CreateCommandElement(MamlCommand command)
new XElement(commandNS + "name", command.Name),
new XElement(commandNS + "verb", verb),
new XElement(commandNS + "noun", noun),
- new XElement(mamlNS + "description", GenerateParagraphs(command.Synopsis))),
- new XElement(mamlNS + "description", GenerateParagraphs(command.Description)),
+ new XElement(mamlNS + "description", GenerateParagraphs(command.Synopsis?.Text))),
+ new XElement(mamlNS + "description", GenerateParagraphs(command.Description?.Text)),
new XElement(commandNS + "syntax", command.Syntax.Select(syn => CreateSyntaxItem(syn, command))),
new XElement(commandNS + "parameters", command.Parameters.Select(param => CreateParameter(param))),
new XElement(commandNS + "inputTypes", command.Inputs.Select(input => CreateInput(input))),
new XElement(commandNS + "returnValues", command.Outputs.Select(output => CreateOutput(output))),
new XElement(mamlNS + "alertSet",
- new XElement(mamlNS + "alert", GenerateParagraphs(command.Notes))),
+ new XElement(mamlNS + "alert", GenerateParagraphs(command.Notes?.Text))),
new XElement(commandNS + "examples", command.Examples.Select(example => CreateExample(example))),
new XElement(commandNS + "relatedLinks", command.Links.Select(link => CreateLink(link))));
}
diff --git a/src/Markdown.MAML/Renderer/Markdownv2Renderer.cs b/src/Markdown.MAML/Renderer/Markdownv2Renderer.cs
index a489ca82..a3dafd3f 100644
--- a/src/Markdown.MAML/Renderer/Markdownv2Renderer.cs
+++ b/src/Markdown.MAML/Renderer/Markdownv2Renderer.cs
@@ -114,7 +114,9 @@ private void AddCommand(MamlCommand command)
private void AddLinks(MamlCommand command)
{
- AddHeader(ModelTransformerBase.COMMAND_ENTRIES_HEADING_LEVEL, MarkdownStrings.RELATED_LINKS);
+ var extraNewLine = command.Links != null && command.Links.Count > 0;
+
+ AddHeader(ModelTransformerBase.COMMAND_ENTRIES_HEADING_LEVEL, MarkdownStrings.RELATED_LINKS, extraNewLine);
foreach (var link in command.Links)
{
if (link.IsSimplifiedTextLink)
@@ -143,7 +145,7 @@ private void AddInputOutput(MamlInputOutput io)
return;
}
- var extraNewLine = string.IsNullOrEmpty(io.Description);
+ var extraNewLine = string.IsNullOrEmpty(io.Description) || ShouldBreak(io.FormatOption);
AddHeader(ModelTransformerBase.INPUT_OUTPUT_TYPENAME_HEADING_LEVEL, io.TypeName, extraNewLine);
AddParagraphs(io.Description);
}
@@ -265,9 +267,18 @@ private string JoinWithComma(IEnumerable args)
return string.Join(", ", args);
}
+ private bool ShouldBreak(SectionFormatOption formatOption)
+ {
+ // If the line break flag is set return true.
+ return formatOption.HasFlag(SectionFormatOption.LineBreakAfterHeader);
+ }
+
private void AddParameter(MamlParameter parameter, MamlCommand command)
{
- AddHeader(ModelTransformerBase.PARAMETERSET_NAME_HEADING_LEVEL, '-' + parameter.Name, extraNewLine: false);
+ var extraNewLine = ShouldBreak(parameter.FormatOption);
+
+ AddHeader(ModelTransformerBase.PARAMETERSET_NAME_HEADING_LEVEL, '-' + parameter.Name, extraNewLine: extraNewLine);
+
// for some reason, in the update mode parameters produces extra newline.
AddParagraphs(parameter.Description, this._mode == ParserMode.FormattingPreserve);
@@ -332,7 +343,10 @@ private void AddExamples(MamlCommand command)
AddHeader(ModelTransformerBase.COMMAND_ENTRIES_HEADING_LEVEL, MarkdownStrings.EXAMPLES);
foreach (var example in command.Examples)
{
- AddHeader(ModelTransformerBase.EXAMPLE_HEADING_LEVEL, example.Title, extraNewLine: false);
+ var extraNewLine = ShouldBreak(example.FormatOption);
+
+ AddHeader(ModelTransformerBase.EXAMPLE_HEADING_LEVEL, example.Title, extraNewLine: extraNewLine);
+
if (!string.IsNullOrEmpty(example.Introduction))
{
AddParagraphs(example.Introduction);
@@ -432,17 +446,17 @@ private void AddSyntax(MamlCommand command)
}
}
- private void AddEntryHeaderWithText(string header, string text)
+ private void AddEntryHeaderWithText(string header, SectionBody body)
{
- AddHeader(ModelTransformerBase.COMMAND_ENTRIES_HEADING_LEVEL, header, extraNewLine: false);
+ var extraNewLine = body == null || string.IsNullOrEmpty(body.Text) || ShouldBreak(body.FormatOption);
+
+ // Add header
+ AddHeader(ModelTransformerBase.COMMAND_ENTRIES_HEADING_LEVEL, header, extraNewLine: extraNewLine);
+
// to correctly handle empty text case, we are adding new-line here
- if (string.IsNullOrEmpty(text))
- {
- _stringBuilder.Append(Environment.NewLine);
- }
- else
+ if (body != null && !string.IsNullOrEmpty(body.Text))
{
- AddParagraphs(text);
+ AddParagraphs(body.Text);
}
}
@@ -525,6 +539,12 @@ private void AddParagraphs(string body, bool noNewLines = false)
body = GetAutoWrappingForMarkdown(paragraphs.Select(para => GetEscapedMarkdownText(para.Trim())).ToArray());
}
+ // The the body already ended in a line break don't add extra lines on to the end
+ if (body.EndsWith("\r\n\r\n"))
+ {
+ noNewLines = true;
+ }
+
_stringBuilder.AppendFormat("{0}{1}{1}", body, noNewLines ? null : Environment.NewLine);
}
diff --git a/src/Markdown.MAML/Renderer/YamlRenderer.cs b/src/Markdown.MAML/Renderer/YamlRenderer.cs
index 2fb2d355..95d2178a 100644
--- a/src/Markdown.MAML/Renderer/YamlRenderer.cs
+++ b/src/Markdown.MAML/Renderer/YamlRenderer.cs
@@ -22,9 +22,9 @@ public static string MamlModelToString(MamlCommand mamlCommand)
var model = new YamlCommand
{
Name = mamlCommand.Name,
- Notes = mamlCommand.Notes,
- Remarks = mamlCommand.Description,
- Summary = mamlCommand.Synopsis,
+ Notes = mamlCommand.Notes.Text,
+ Remarks = mamlCommand.Description.Text,
+ Summary = mamlCommand.Synopsis.Text,
Examples = mamlCommand.Examples.Select(CreateExample).ToList(),
Inputs = mamlCommand.Inputs.Select(CreateInputOutput).ToList(),
Links = mamlCommand.Links.Select(CreateLink).ToList(),
diff --git a/src/Markdown.MAML/Transformer/MamlModelMerger.cs b/src/Markdown.MAML/Transformer/MamlModelMerger.cs
index 8b413c32..f08aaf48 100644
--- a/src/Markdown.MAML/Transformer/MamlModelMerger.cs
+++ b/src/Markdown.MAML/Transformer/MamlModelMerger.cs
@@ -1,4 +1,5 @@
using Markdown.MAML.Model.MAML;
+using Markdown.MAML.Model.Markdown;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -36,18 +37,9 @@ public MamlCommand Merge(MamlCommand metadataModel, MamlCommand stringModel)
result = new MamlCommand()
{
Name = metadataModel.Name,
- Synopsis = metadataStringCompare(metadataModel.Synopsis,
- stringModel.Synopsis,
- metadataModel.Name,
- "synopsis"),
- Description = metadataStringCompare(metadataModel.Description,
- stringModel.Description,
- metadataModel.Name,
- "description"),
- Notes = metadataStringCompare(metadataModel.Notes,
- stringModel.Notes,
- metadataModel.Name,
- "notes"),
+ Synopsis = stringModel.Synopsis,
+ Description = stringModel.Description,
+ Notes = stringModel.Notes,
Extent = stringModel.Extent
};
}
@@ -95,8 +87,6 @@ public MamlCommand Merge(MamlCommand metadataModel, MamlCommand stringModel)
//Result takes in the merged parameter results.
MergeParameters(result, metadataModel, stringModel);
-
-
if (!_cmdletUpdated)
{
Report("\tNo updates done\r\n");
@@ -192,11 +182,7 @@ private void MergeParameters(MamlCommand result, MamlCommand metadataModel, Maml
{
try
{
- param.Description = metadataStringCompare(param.Description,
- strParam.Description,
- metadataModel.Name,
- param.Name,
- "parameter description");
+ param.Description = strParam.Description;
}
catch (Exception ex)
{
@@ -228,6 +214,8 @@ private void MergeParameters(MamlCommand result, MamlCommand metadataModel, Maml
_cmdletUpdated = true;
}
+ // Update the parameter with the merged in FormatOption
+ param.FormatOption = strParam.FormatOption;
}
result.Parameters.Add(param);
@@ -286,42 +274,6 @@ private void MergeParameters(MamlCommand result, MamlCommand metadataModel, Maml
Report($" Exception parameter merge: \r\n{ex.Message}\r\n");
_cmdletUpdated = true;
}
-
-
- }
-
- ///
- /// Compares parameters
- ///
- private string metadataStringCompare(string metadataContent, string stringContent, string moduleName, string paramName, string contentItemName)
- {
- var pretifiedStringContent = stringContent == null ? "" : Pretify(stringContent).TrimEnd(' ');
- var pretifiedMetadataContent = metadataContent == null ? "" : Pretify(metadataContent).TrimEnd(' ');
-
- return stringContent;
- }
-
- ///
- /// Cleans the extra \r\n and inserts a tab at the beginning of new lines, mid paragraphs
- ///
- private static string Pretify(string multiLineText)
- {
- if(string.IsNullOrEmpty(multiLineText))
- {
- multiLineText = "";
- }
- return Regex.Replace(multiLineText, "(\r\n)+", "\r\n ");
- }
-
- ///
- /// Compares Cmdlet values: Synopsis, Description, and Notes. Preserves the content from the string model (old) or the metadata model (new).
- ///
- private string metadataStringCompare(string metadataContent, string stringContent, string moduleName, string contentItemName)
- {
- var metadataContentPretified = (metadataContent == null ? "" : Pretify(metadataContent).TrimEnd(' '));
- var stringContentPretified = (stringContent == null ? "" : Pretify(stringContent).TrimEnd(' '));
-
- return stringContent;
}
private void Report(string format, params object[] objects)
diff --git a/src/Markdown.MAML/Transformer/MamlMultiModelMerger.cs b/src/Markdown.MAML/Transformer/MamlMultiModelMerger.cs
index dd660b35..945d29f9 100644
--- a/src/Markdown.MAML/Transformer/MamlMultiModelMerger.cs
+++ b/src/Markdown.MAML/Transformer/MamlMultiModelMerger.cs
@@ -1,4 +1,5 @@
using Markdown.MAML.Model.MAML;
+using Markdown.MAML.Model.Markdown;
using System;
using System.Collections;
using System.Collections.Generic;
@@ -48,9 +49,9 @@ public MamlCommand Merge(Dictionary applicableTag2Model)
result = new MamlCommand()
{
Name = referenceModel.Name,
- Synopsis = MergeText(tagsModel.ToDictionary(pair => pair.Key, pair => pair.Value.Synopsis)),
- Description = MergeText(tagsModel.ToDictionary(pair => pair.Key, pair => pair.Value.Description)),
- Notes = MergeText(tagsModel.ToDictionary(pair => pair.Key, pair => pair.Value.Notes)),
+ Synopsis = new SectionBody(MergeText(tagsModel.ToDictionary(pair => pair.Key, pair => pair.Value.Synopsis.Text))),
+ Description = new SectionBody(MergeText(tagsModel.ToDictionary(pair => pair.Key, pair => pair.Value.Description.Text))),
+ Notes = new SectionBody(MergeText(tagsModel.ToDictionary(pair => pair.Key, pair => pair.Value.Notes.Text))),
Extent = referenceModel.Extent
};
diff --git a/src/Markdown.MAML/Transformer/ModelTransformerBase.cs b/src/Markdown.MAML/Transformer/ModelTransformerBase.cs
index f861b3d1..b6b1a60a 100644
--- a/src/Markdown.MAML/Transformer/ModelTransformerBase.cs
+++ b/src/Markdown.MAML/Transformer/ModelTransformerBase.cs
@@ -176,6 +176,7 @@ protected MamlExample ExampleRule()
Title = headingNode.Text
};
example.Introduction = GetTextFromParagraphNode(ParagraphNodeRule());
+ example.FormatOption = headingNode.FormatOption;
CodeBlockNode codeBlock;
while ((codeBlock = CodeBlockRule()) != null)
{
@@ -252,11 +253,11 @@ protected MamlInputOutput InputOutputRule()
MamlInputOutput typeEntity = new MamlInputOutput()
{
- TypeName = headingNode.Text
+ TypeName = headingNode.Text,
+ Description = SimpleTextSectionRule(),
+ FormatOption = headingNode.FormatOption
};
- typeEntity.Description = SimpleTextSectionRule();
-
return typeEntity;
}
diff --git a/src/Markdown.MAML/Transformer/ModelTransformerVersion2.cs b/src/Markdown.MAML/Transformer/ModelTransformerVersion2.cs
index b2b4d636..aeb5c76b 100644
--- a/src/Markdown.MAML/Transformer/ModelTransformerVersion2.cs
+++ b/src/Markdown.MAML/Transformer/ModelTransformerVersion2.cs
@@ -47,12 +47,12 @@ override protected bool SectionDispatch(MamlCommand command)
{
case "DESCRIPTION":
{
- command.Description = SimpleTextSectionRule();
+ command.Description = new SectionBody(SimpleTextSectionRule(), headingNode.FormatOption);
break;
}
case "SYNOPSIS":
{
- command.Synopsis = SimpleTextSectionRule();
+ command.Synopsis = new SectionBody(SimpleTextSectionRule(), headingNode.FormatOption);
break;
}
case "SYNTAX":
@@ -82,7 +82,7 @@ override protected bool SectionDispatch(MamlCommand command)
}
case "NOTES":
{
- command.Notes = SimpleTextSectionRule();
+ command.Notes = new SectionBody(SimpleTextSectionRule(), headingNode.FormatOption);
break;
}
case "RELATED LINKS":
@@ -378,6 +378,7 @@ private bool ParameterRule(MamlCommand commmand)
};
parameter.Description = ParagraphOrCodeBlockNodeRule("yaml");
+ parameter.FormatOption = headingNode.FormatOption;
if (StringComparer.OrdinalIgnoreCase.Equals(parameter.Name, MarkdownStrings.CommonParametersToken))
{
diff --git a/src/platyPS/platyPS.psm1 b/src/platyPS/platyPS.psm1
index b7ae116a..2a2e6687 100644
--- a/src/platyPS/platyPS.psm1
+++ b/src/platyPS/platyPS.psm1
@@ -427,7 +427,7 @@ function Update-MarkdownHelp
}
$md = ConvertMamlModelToMarkdown -mamlCommand $newModel -metadata $metadata -PreserveFormatting
- MySetContent -path $file.FullName -value $md -Encoding $Encoding -Force # yeild
+ MySetContent -path $file.FullName -value $md -Encoding $Encoding -Force # yield
}
}
}
@@ -2276,7 +2276,7 @@ function ConvertPsObjectsToMamlModel
#Get Description
#Not provided by the command object.
- $MamlCommandObject.Description = "{{Fill in the Description}}"
+ $MamlCommandObject.Description = New-Object -TypeName Markdown.MAML.Model.Markdown.SectionBody ("{{Fill in the Description}}")
#endregion
@@ -2457,24 +2457,24 @@ function ConvertPsObjectsToMamlModel
# Help object ALWAYS contains SYNOPSIS.
# If it's not available, it's auto-generated.
# We don't want to include auto-generated SYNOPSIS (see https://github.com/PowerShell/platyPS/issues/110)
- $MamlCommandObject.Synopsis = "{{Fill in the Synopsis}}"
+ $MamlCommandObject.Synopsis = New-Object -TypeName Markdown.MAML.Model.Markdown.SectionBody ("{{Fill in the Synopsis}}")
}
else
{
- $MamlCommandObject.Synopsis = $Help.Synopsis.Trim()
+ $MamlCommandObject.Synopsis = New-Object -TypeName Markdown.MAML.Model.Markdown.SectionBody ($Help.Synopsis.Trim())
}
#Get Description
if($Help.description -ne $null)
{
- $MamlCommandObject.Description = $Help.description.Text | AddLineBreaksForParagraphs
+ $MamlCommandObject.Description = New-Object -TypeName Markdown.MAML.Model.Markdown.SectionBody ($Help.description.Text | AddLineBreaksForParagraphs)
}
#Add to Notes
#From the Help AlertSet data
if($help.alertSet)
{
- $MamlCommandObject.Notes = $help.alertSet.alert.Text | AddLineBreaksForParagraphs
+ $MamlCommandObject.Notes = New-Object -TypeName Markdown.MAML.Model.Markdown.SectionBody ($help.alertSet.alert.Text | AddLineBreaksForParagraphs)
}
# Not provided by the command object. Using the Command Type to create a note declaring it's type.
diff --git a/test/Markdown.MAML.Test/EndToEnd/EndToEndTests.cs b/test/Markdown.MAML.Test/EndToEnd/EndToEndTests.cs
index 55cd7fb4..eaf93488 100644
--- a/test/Markdown.MAML.Test/EndToEnd/EndToEndTests.cs
+++ b/test/Markdown.MAML.Test/EndToEnd/EndToEndTests.cs
@@ -5,6 +5,7 @@
using Xunit;
using Markdown.MAML.Parser;
using Markdown.MAML.Transformer;
+using System.Linq;
namespace Markdown.MAML.Test.EndToEnd
{
@@ -47,6 +48,118 @@ And this is my last line.
Assert.Equal(3, description.Length);
}
+ [Fact]
+ public void PreserveMarkdownWhenUpdatingMarkdownHelp()
+ {
+ var expected = @"# Update-MarkdownHelp
+
+## SYNOPSIS
+
+Example markdown to test that markdown is preserved.
+
+## SYNTAX
+
+```
+Update-MarkdownHelp [-Name] [-Path ]
+```
+
+## DESCRIPTION
+When calling Update-MarkdownHelp line breaks should be preserved.
+
+## EXAMPLES
+
+### Example 1: With no line break or description
+```
+PS C:\> Update-MarkdownHelp
+```
+
+This is example 1 remark.
+
+### Example 2: With no line break
+This is an example description.
+
+```
+PS C:\> Update-MarkdownHelp
+```
+
+This is example 2 remark.
+
+### Example 3: With line break and no description
+
+```
+PS C:\> Update-MarkdownHelp
+```
+
+This is example 3 remark.
+
+### Example 4: With line break and description
+
+This is an example description.
+
+```
+PS C:\> Update-MarkdownHelp
+```
+
+This is example 4 remark.
+
+## PARAMETERS
+
+### -Name
+
+Parameter name description with line break.
+
+```yaml
+Type: String
+Parameter Sets: (All)
+Aliases:
+
+Required: True
+Position: 1
+Default value: None
+Accept pipeline input: False
+Accept wildcard characters: False
+```
+
+### -Path
+Parameter path description with no line break.
+
+```yaml
+Type: String
+Parameter Sets: (All)
+Aliases:
+
+Required: False
+Position: Named
+Default value: None
+Accept pipeline input: False
+Accept wildcard characters: False
+```
+
+## INPUTS
+
+### String[]
+
+This is an input description.
+
+## OUTPUTS
+
+### System.Object
+
+This is an output description.
+
+## NOTES
+
+## RELATED LINKS
+";
+
+ // Parse markdown and convert back to markdown to make sure there are no changes
+ var actualFull = MarkdownStringToMarkdownString(expected, ParserMode.Full);
+ var actualFormattingPreserve = MarkdownStringToMarkdownString(expected, ParserMode.FormattingPreserve);
+
+ Assert.Equal(expected, actualFull);
+ Assert.Equal(expected, actualFormattingPreserve);
+ }
+
[Fact]
public void CanUseSharpInsideParagraphs()
{
@@ -386,5 +499,20 @@ public static string MarkdownStringToMamlString(string markdown)
return maml;
}
+
+ private string MarkdownStringToMarkdownString(string markdown, ParserMode parserMode)
+ {
+ // Parse
+ var parser = new MarkdownParser();
+ var markdownModel = parser.ParseString(new string[] { markdown }, ParserMode.FormattingPreserve, null);
+
+ // Convert model to Maml
+ var transformer = new ModelTransformerVersion2();
+ var mamlModel = transformer.NodeModelToMamlModel(markdownModel).FirstOrDefault();
+
+ // Render as markdown
+ var renderer = new MarkdownV2Renderer(parserMode);
+ return renderer.MamlModelToString(mamlModel, true);
+ }
}
}
diff --git a/test/Markdown.MAML.Test/Parser/ParserTests.cs b/test/Markdown.MAML.Test/Parser/ParserTests.cs
index 26d77fd1..fb14b9de 100644
--- a/test/Markdown.MAML.Test/Parser/ParserTests.cs
+++ b/test/Markdown.MAML.Test/Parser/ParserTests.cs
@@ -4,6 +4,7 @@
using Markdown.MAML.Model.Markdown;
using Markdown.MAML.Parser;
using Xunit;
+using System.Collections.Generic;
namespace Markdown.MAML.Test.Parser
{
@@ -589,6 +590,83 @@ Deletes entries from the command history.
Assert.Equal(descriptionText, paragraphNode.Spans.First().Text);
}
+ [Fact]
+ public void PreservesLineBreakAfterHeaderWithHashPrefix()
+ {
+ var expectedSynopsis = "This is the synopsis text.";
+ var expectedDescription = "This is the description text.";
+
+ // Parse markdown
+ var documentNode = MarkdownStringToDocumentNode($"## SYNOPSIS\r\n{expectedSynopsis}\r\n\r\n## DESCRIPTION\r\n\r\n{expectedDescription}");
+
+ // Get results
+ var actualSynopsis = GetParagraph(documentNode, "SYNOPSIS").Spans.FirstOrDefault().Text;
+ var actualDescription = GetParagraph(documentNode, "DESCRIPTION").Spans.FirstOrDefault().Text;
+ var synopsisHasLineBreak = GetHeading(documentNode, "SYNOPSIS").FormatOption == SectionFormatOption.LineBreakAfterHeader;
+ var descriptionHasLineBreak = GetHeading(documentNode, "DESCRIPTION").FormatOption == SectionFormatOption.LineBreakAfterHeader;
+
+ // Check that text matches and line breaks haven't been captured as text
+ Assert.Equal(expectedSynopsis, actualSynopsis);
+ Assert.Equal(expectedDescription, actualDescription);
+
+ // Does not use line break and should not be added
+ Assert.Equal(false, synopsisHasLineBreak);
+
+ // Uses line break and should be preserved
+ Assert.Equal(true, descriptionHasLineBreak);
+ }
+
+ [Fact]
+ public void PreservesLineBreakAfterParameter()
+ {
+ var expectedP1 = "Name parameter description.";
+ var expectedP2 = "Path parameter description.";
+
+ // Parse markdown
+ var documentNode = MarkdownStringToDocumentNode($"## PARAMETERS\r\n\r\n### -Name\r\n{expectedP1}\r\n\r\n```yaml\r\n```\r\n\r\n### -Path\r\n\r\n{expectedP2}");
+
+ var actualP1 = GetParagraph(documentNode, "-Name").Spans.FirstOrDefault().Text;
+ var actualP2 = GetParagraph(documentNode, "-Path").Spans.FirstOrDefault().Text;
+ var hasLineBreakP1 = GetHeading(documentNode, "-Name").FormatOption == SectionFormatOption.LineBreakAfterHeader;
+ var hasLineBreakP2 = GetHeading(documentNode, "-Path").FormatOption == SectionFormatOption.LineBreakAfterHeader;
+
+ // Check that text matches and line breaks haven't been captured as text
+ Assert.Equal(expectedP1, actualP1);
+ Assert.Equal(expectedP2, actualP2);
+
+ // Does not use line break and should not be added
+ Assert.Equal(false, hasLineBreakP1);
+
+ // Uses line break and should be preserved
+ Assert.Equal(true, hasLineBreakP2);
+ }
+
+ [Fact]
+ public void PreservesLineBreakAfterHeaderWithUnderlines()
+ {
+ var expectedSynopsis = "This is the synopsis text.";
+ var expectedDescription = "This is the description text.";
+
+ // Parse markdown
+ var documentNode = MarkdownStringToDocumentNode($"SYNOPSIS\r\n---\r\n{expectedSynopsis}\r\n\r\nDESCRIPTION\r\n---\r\n\r\n{expectedDescription}");
+
+ // Get results
+ var actualSynopsis = GetParagraph(documentNode, "SYNOPSIS").Spans.FirstOrDefault().Text;
+ var actualDescription = GetParagraph(documentNode, "DESCRIPTION").Spans.FirstOrDefault().Text;
+ var synopsisHasLineBreak = GetHeading(documentNode, "SYNOPSIS").FormatOption == SectionFormatOption.LineBreakAfterHeader;
+ var descriptionHasLineBreak = GetHeading(documentNode, "DESCRIPTION").FormatOption == SectionFormatOption.LineBreakAfterHeader;
+
+ // Check that text matches and line breaks haven't been captured as text
+ Assert.Equal(expectedSynopsis, actualSynopsis);
+ Assert.Equal(expectedDescription, actualDescription);
+
+ // Does not use line break and should not be added
+ Assert.Equal(false, synopsisHasLineBreak);
+
+ // Uses line break and should be preserved
+ Assert.Equal(true, descriptionHasLineBreak);
+ }
+
private TNode ParseAndGetExpectedChild(
string markdownString,
MarkdownNodeType expectedNodeType)
@@ -609,6 +687,30 @@ private TNode AssertNodeType(
return Assert.IsType(markdownNode);
}
+ private ParagraphNode GetParagraph(DocumentNode documentNode, string heading)
+ {
+ return documentNode
+ .Children
+
+ // Skip until we reach the heading
+ .SkipWhile(node => node.NodeType != MarkdownNodeType.Heading || (node as HeadingNode).Text != heading)
+
+ // Get the next paragraph after the heading
+ .Skip(1)
+ .OfType()
+ .FirstOrDefault();
+ }
+
+ private HeadingNode GetHeading(DocumentNode documentNode, string text = null)
+ {
+ return documentNode
+ .Children
+ .OfType()
+
+ // If heading was specified, get the specific heading
+ .FirstOrDefault(node => string.IsNullOrEmpty(text) || node.Text == text);
+ }
+
private DocumentNode MarkdownStringToDocumentNode(string markdown)
{
var parser = new MarkdownParser();
diff --git a/test/Markdown.MAML.Test/Renderer/MamlRendererTests.cs b/test/Markdown.MAML.Test/Renderer/MamlRendererTests.cs
index 8d52e9c3..87eda389 100644
--- a/test/Markdown.MAML.Test/Renderer/MamlRendererTests.cs
+++ b/test/Markdown.MAML.Test/Renderer/MamlRendererTests.cs
@@ -7,6 +7,7 @@
using Xunit;
using Markdown.MAML.Test.EndToEnd;
using Markdown.MAML.Model.MAML;
+using Markdown.MAML.Model.Markdown;
namespace Markdown.MAML.Test.Renderer
{
@@ -19,8 +20,8 @@ public void RendererProduceNameAndSynopsis()
MamlCommand command = new MamlCommand()
{
Name = "Get-Foo",
- Synopsis = "This is the synopsis",
- Description = "This is a long description."
+ Synopsis = new SectionBody("This is the synopsis"),
+ Description = new SectionBody("This is a long description.")
};
command.Parameters.Add(new MamlParameter()
@@ -28,7 +29,7 @@ public void RendererProduceNameAndSynopsis()
Type = "String",
Name = "Name",
Required = true,
- Description = "Parameter Description.",
+ Description = "This is the name parameter description.",
VariableLength = true,
Globbing = true,
PipelineInput = "True (ByValue)",
@@ -36,6 +37,19 @@ public void RendererProduceNameAndSynopsis()
Aliases = new string []{"GF","Foos","Do"},
}
);
+ command.Parameters.Add(new MamlParameter()
+ {
+ Type = "String",
+ Name = "Path",
+ Required = true,
+ Description = "This is the path parameter description.",
+ VariableLength = true,
+ Globbing = true,
+ PipelineInput = "True (ByValue)",
+ Position = "2",
+ Aliases = new string[] { },
+ }
+ );
command.Inputs.Add(new MamlInputOutput()
{
TypeName = "String",
@@ -73,6 +87,22 @@ public void RendererProduceNameAndSynopsis()
string[] synopsis = EndToEndTests.GetXmlContent(maml, "/msh:helpItems/command:command/command:details/maml:description/maml:para");
Assert.Equal(1, synopsis.Length);
Assert.Equal("This is the synopsis", synopsis[0]);
+
+ string[] description = EndToEndTests.GetXmlContent(maml, "/msh:helpItems/command:command/maml:description/maml:para");
+ Assert.Equal(1, description.Length);
+ Assert.Equal("This is a long description.", description[0]);
+
+ string[] parameter1 = EndToEndTests.GetXmlContent(maml, "/msh:helpItems/command:command/command:parameters/command:parameter[maml:name='Name']/maml:Description/maml:para");
+ Assert.Equal(1, parameter1.Length);
+ Assert.Equal("This is the name parameter description.", parameter1[0]);
+
+ string[] parameter2 = EndToEndTests.GetXmlContent(maml, "/msh:helpItems/command:command/command:parameters/command:parameter[maml:name='Path']/maml:Description/maml:para");
+ Assert.Equal(1, parameter2.Length);
+ Assert.Equal("This is the path parameter description.", parameter2[0]);
+
+ string[] example1 = EndToEndTests.GetXmlContent(maml, "/msh:helpItems/command:command/command:examples/command:example[maml:title='Example 1']/dev:code");
+ Assert.Equal(1, example1.Length);
+ Assert.Equal("PS:> Get-Help -YouNeedIt", example1[0]);
}
[Fact]
@@ -130,14 +160,14 @@ public void RendererProduceEscapeXmlSpecialChars()
MamlCommand command = new MamlCommand()
{
Name = "Get-Foo",
- Synopsis = "" // < and > should be properly escaped
+ Synopsis = new SectionBody("") // < and > should be properly escaped
};
string maml = renderer.MamlModelToString(new[] { command });
string[] synopsis = EndToEndTests.GetXmlContent(maml, "/msh:helpItems/command:command/command:details/maml:description/maml:para");
Assert.Equal(1, synopsis.Length);
- Assert.Equal(synopsis[0], command.Synopsis);
+ Assert.Equal(synopsis[0], command.Synopsis.Text);
}
}
diff --git a/test/Markdown.MAML.Test/Renderer/MarkdownV2RendererTests.cs b/test/Markdown.MAML.Test/Renderer/MarkdownV2RendererTests.cs
index f977f96d..6127df2f 100644
--- a/test/Markdown.MAML.Test/Renderer/MarkdownV2RendererTests.cs
+++ b/test/Markdown.MAML.Test/Renderer/MarkdownV2RendererTests.cs
@@ -8,6 +8,7 @@
using Xunit;
using System.Collections;
using Markdown.MAML.Parser;
+using Markdown.MAML.Model.Markdown;
namespace Markdown.MAML.Test.Renderer
{
@@ -56,6 +57,130 @@ public void ReturnsSyntaxString()
Assert.Equal("Get-Foo [-Bar ] []", syntaxString);
}
+ [Fact]
+ public void RendererIgnoresLineBreakWhenBodyIsEmpty()
+ {
+ var renderer = new MarkdownV2Renderer(ParserMode.Full);
+ MamlCommand command = new MamlCommand()
+ {
+ Name = "Test-LineBreak",
+ Notes = new SectionBody("", SectionFormatOption.LineBreakAfterHeader)
+ };
+
+ string markdown = renderer.MamlModelToString(command, null);
+
+ Assert.DoesNotContain("\r\n\r\n\r\n", markdown);
+ }
+
+ [Fact]
+ public void RendererLineBreakAfterParameter()
+ {
+ var renderer = new MarkdownV2Renderer(ParserMode.Full);
+
+ MamlCommand command = new MamlCommand()
+ {
+ Name = "Test-LineBreak",
+ Synopsis = new SectionBody("This is the synopsis"),
+ Description = new SectionBody("This is a long description"),
+ Notes = new SectionBody("This is a note")
+ };
+
+ var parameter1 = new MamlParameter()
+ {
+ Type = "String",
+ Name = "Name",
+ Required = true,
+ Description = "Name description.",
+ Globbing = true
+ };
+
+ var parameter2 = new MamlParameter()
+ {
+ Type = "String",
+ Name = "Path",
+ FormatOption = SectionFormatOption.LineBreakAfterHeader,
+ Required = true,
+ Description = "Path description.",
+ Globbing = true
+ };
+
+ command.Parameters.Add(parameter1);
+ command.Parameters.Add(parameter2);
+
+ var syntax1 = new MamlSyntax()
+ {
+ ParameterSetName = "ByName"
+ };
+
+ syntax1.Parameters.Add(parameter1);
+ syntax1.Parameters.Add(parameter2);
+ command.Syntax.Add(syntax1);
+
+ string markdown = renderer.MamlModelToString(command, null);
+
+ // Does not use line break and should not be added
+ Assert.Contains("### -Name\r\nName description.", markdown);
+
+ // Uses line break and should be preserved
+ Assert.Contains("### -Path\r\n\r\nPath description.", markdown);
+ }
+
+ [Fact]
+ public void RendererLineBreakAfterExample()
+ {
+ var renderer = new MarkdownV2Renderer(ParserMode.Full);
+
+ MamlCommand command = new MamlCommand()
+ {
+ Name = "Test-LineBreak",
+ };
+
+ var example1 = new MamlExample()
+ {
+ Title = "Example 1",
+ Code = "PS C:\\> Get-Help",
+ Remarks = "This is an example to get help."
+ };
+
+ var example2 = new MamlExample()
+ {
+ Title = "Example 2",
+ Code = "PS C:\\> Get-Help -Full",
+ Introduction = "Intro"
+ };
+
+ var example3 = new MamlExample()
+ {
+ Title = "Example 3",
+ FormatOption = SectionFormatOption.LineBreakAfterHeader,
+ Code = "PS C:\\> Get-Help",
+ Remarks = "This is an example to get help."
+ };
+
+ var example4 = new MamlExample()
+ {
+ Title = "Example 4",
+ FormatOption = SectionFormatOption.LineBreakAfterHeader,
+ Code = "PS C:\\> Get-Help -Full",
+ Introduction = "Intro"
+ };
+
+ command.Examples.Add(example1);
+ command.Examples.Add(example2);
+ command.Examples.Add(example3);
+ command.Examples.Add(example4);
+
+ string markdown = renderer.MamlModelToString(command, null);
+
+ // Does not use line break and should not be added
+ Assert.Contains("### Example 1\r\n```", markdown);
+ Assert.Contains("### Example 2\r\nIntro\r\n\r\n```", markdown);
+
+ // Uses line break and should be preserved
+ Assert.Contains("### Example 3\r\n\r\n```", markdown);
+ Assert.Contains("### Example 4\r\n\r\nIntro\r\n\r\n```", markdown);
+ }
+
[Fact]
public void RendererCreatesWorkflowParametersEntry()
{
@@ -104,7 +229,6 @@ Workflow [] []
## NOTES
## RELATED LINKS
-
", markdown);
}
@@ -115,7 +239,7 @@ public void RendererNormalizeQuotesAndDashes()
MamlCommand command = new MamlCommand()
{
Name = "Test-Quotes",
- Description = @"”“‘’––-"
+ Description = new SectionBody(@"”“‘’––-")
};
string markdown = renderer.MamlModelToString(command, null);
@@ -147,7 +271,6 @@ public void RendererNormalizeQuotesAndDashes()
## NOTES
## RELATED LINKS
-
", markdown);
}
@@ -158,9 +281,9 @@ public void RendererProduceMarkdownV2Output()
MamlCommand command = new MamlCommand()
{
Name = "Get-Foo",
- Synopsis = "This is the synopsis",
- Description = "This is a long description.\r\nWith two paragraphs. And the second one contains of few line! They should be auto-wrapped. Because, why not? We can do that kind of the things, no problem.\r\n\r\n-- Foo. Bar.\r\n-- Don't break. The list.\r\n-- Into. Pieces",
- Notes = "This is a multiline note.\r\nSecond line."
+ Synopsis = new SectionBody("This is the synopsis"),
+ Description = new SectionBody("This is a long description.\r\nWith two paragraphs. And the second one contains of few line! They should be auto-wrapped. Because, why not? We can do that kind of the things, no problem.\r\n\r\n-- Foo. Bar.\r\n-- Don't break. The list.\r\n-- Into. Pieces"),
+ Notes = new SectionBody("This is a multiline note.\r\nSecond line.")
};
var parameter = new MamlParameter()
@@ -460,7 +583,6 @@ public void RenderesAllParameterSetMoniker()
## NOTES
## RELATED LINKS
-
", markdown);
}
@@ -472,7 +594,7 @@ public void RenderesWithPreservedFormatting()
{
Name = "Get-Foo",
SupportCommonParameters = false,
- Description = @"Hello
+ Description = new SectionBody(@"Hello
This \ should be preserved by renderer
With all [hyper](https://links.com) and yada
-- yada
@@ -483,7 +605,7 @@ With all [hyper](https://links.com) and yada
* [ ] But
* [ ] It should be left"
- };
+ )};
command.Links.Add(
new MamlLink(isSimplifiedTextLink: true)
diff --git a/test/Markdown.MAML.Test/Renderer/YamlRendererTests.cs b/test/Markdown.MAML.Test/Renderer/YamlRendererTests.cs
index 50c6e82c..48bb359d 100644
--- a/test/Markdown.MAML.Test/Renderer/YamlRendererTests.cs
+++ b/test/Markdown.MAML.Test/Renderer/YamlRendererTests.cs
@@ -9,6 +9,7 @@
using Xunit;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
+using Markdown.MAML.Model.Markdown;
namespace Markdown.MAML.Test.Renderer
{
@@ -27,9 +28,9 @@ public void RendererProducesNameAndTextFields()
Assert.NotNull(writtenModel);
Assert.Equal(model.Name, writtenModel.Name);
- Assert.Equal(model.Description, writtenModel.Remarks);
- Assert.Equal(model.Synopsis, writtenModel.Summary);
- Assert.Equal(model.Notes, writtenModel.Notes);
+ Assert.Equal(model.Description.Text, writtenModel.Remarks);
+ Assert.Equal(model.Synopsis.Text, writtenModel.Summary);
+ Assert.Equal(model.Notes.Text, writtenModel.Notes);
}
[Fact]
@@ -206,9 +207,9 @@ private static MamlCommand CreateModel()
var command = new MamlCommand
{
Name = "Test-Unit",
- Description = "A test cmdlet",
- Synopsis = "A cmdlet to test",
- Notes = "This is just a test",
+ Description = new SectionBody("A test cmdlet"),
+ Synopsis = new SectionBody("A cmdlet to test"),
+ Notes = new SectionBody("This is just a test"),
ModuleName = "TestModule"
};
diff --git a/test/Markdown.MAML.Test/Transformer/MamlModelMergerTests.cs b/test/Markdown.MAML.Test/Transformer/MamlModelMergerTests.cs
index 10d479ed..b2c1a69c 100644
--- a/test/Markdown.MAML.Test/Transformer/MamlModelMergerTests.cs
+++ b/test/Markdown.MAML.Test/Transformer/MamlModelMergerTests.cs
@@ -1,4 +1,5 @@
using Markdown.MAML.Model.MAML;
+using Markdown.MAML.Model.Markdown;
using Markdown.MAML.Transformer;
using System;
using System.Collections.Generic;
@@ -22,8 +23,8 @@ public void RendererProduceMarkdownV2Output()
var result = merger.Merge(metadataCommand, originalCommand);
- Assert.Equal(2, result.Parameters.Count);
- Assert.Equal(2, originalCommand.Parameters.Count);
+ Assert.Equal(3, result.Parameters.Count);
+ Assert.Equal(3, originalCommand.Parameters.Count);
Assert.Equal("Name", result.Parameters[0].Name);
Assert.Equal("NewParam", result.Parameters[1].Name);
Assert.Contains("Parameter Updated: Name", _reportStream);
@@ -35,15 +36,18 @@ public void RendererProduceMarkdownV2Output()
Assert.Contains("Parameter Deleted: Remove", _reportStream);
Assert.Contains("---- UPDATING Cmdlet : Get-Foo ----", _reportStream);
Assert.Contains("---- COMPLETED UPDATING Cmdlet : Get-Foo ----\r\n\r\n", _reportStream);
-
+ Assert.Equal(originalCommand.Synopsis.Text, result.Synopsis.Text);
+ Assert.Equal(originalCommand.Description.Text, result.Description.Text);
+ Assert.Equal(originalCommand.Notes.Text, result.Notes.Text);
Assert.Equal(originalCommand.Parameters[0].Description, result.Parameters[0].Description);
+ Assert.Equal(originalCommand.Parameters[0].FormatOption, result.Parameters[0].FormatOption);
+ Assert.Equal(originalCommand.Parameters[2].Description, result.Parameters[2].Description);
+ Assert.Equal(originalCommand.Parameters[2].FormatOption, result.Parameters[2].FormatOption);
Assert.Equal(originalCommand.Links.Count, result.Links.Count);
Assert.Equal(originalCommand.Links[0].LinkName, result.Links[0].LinkName);
Assert.Equal(originalCommand.Links[0].LinkUri, result.Links[0].LinkUri);
-
-
}
private void WriteMessage(string message)
@@ -56,9 +60,9 @@ private MamlCommand GetOriginal()
MamlCommand originalCommand = new MamlCommand()
{
Name = "Get-Foo",
- Synopsis = "This is the synopsis",
- Description = "This is a long description.\r\nWith two paragraphs.",
- Notes = "This is a multiline note.\r\nSecond line."
+ Synopsis = new SectionBody("This is the synopsis"),
+ Description = new SectionBody("This is a long description.\r\nWith two paragraphs."),
+ Notes = new SectionBody("This is a multiline note.\r\nSecond line.")
};
var parameterName = new MamlParameter()
@@ -87,9 +91,19 @@ private MamlCommand GetOriginal()
DefaultValue = "dodododo",
Aliases = new string[] { "Pa1", "RemovedParam", "Gone" },
};
+ var parameterPath = new MamlParameter()
+ {
+ Type = "String",
+ Name = "Path",
+ Required = true,
+ Description = "Parameter path description.",
+ FormatOption = SectionFormatOption.LineBreakAfterHeader,
+ Globbing = true
+ };
originalCommand.Parameters.Add(parameterName);
originalCommand.Parameters.Add(removedParameterName);
+ originalCommand.Parameters.Add(parameterPath);
var syntax1 = new MamlSyntax()
{
@@ -97,6 +111,7 @@ private MamlCommand GetOriginal()
};
syntax1.Parameters.Add(parameterName);
syntax1.Parameters.Add(removedParameterName);
+ syntax1.Parameters.Add(parameterPath);
originalCommand.Syntax.Add(syntax1);
var syntax2 = new MamlSyntax()
@@ -105,10 +120,9 @@ private MamlCommand GetOriginal()
IsDefault = true
};
syntax2.Parameters.Add(parameterName);
+ syntax2.Parameters.Add(parameterPath);
originalCommand.Syntax.Add(syntax2);
-
-
originalCommand.Inputs.Add(new MamlInputOutput()
{
TypeName = "String",
@@ -150,9 +164,9 @@ private MamlCommand GetRegenerated()
MamlCommand metadataCommand = new MamlCommand()
{
Name = "Get-Foo",
- Description = "This is a long description.\r\nWith two paragraphs.",
- Synopsis = "This is a old synopsis.",
- Notes = "These are old notes"
+ Description = new SectionBody("This is a long description.\r\nWith two paragraphs."),
+ Synopsis = new SectionBody("This is a old synopsis."), // DIFF!!
+ Notes = new SectionBody("These are old notes") // DIFF!!
};
var parameterName1 = new MamlParameter()
@@ -175,8 +189,18 @@ private MamlCommand GetRegenerated()
Description = "Old Param Description"
};
+ var parameterPath = new MamlParameter()
+ {
+ Type = "String",
+ Name = "Path",
+ Required = true,
+ Description = "Parameter path description.",
+ Globbing = true
+ };
+
metadataCommand.Parameters.Add(parameterName1);
metadataCommand.Parameters.Add(parameterNew);
+ metadataCommand.Parameters.Add(parameterPath);
var syntax3 = new MamlSyntax()
{
@@ -185,6 +209,7 @@ private MamlCommand GetRegenerated()
syntax3.Parameters.Add(parameterName1);
syntax3.Parameters.Add(parameterNew);
+ syntax3.Parameters.Add(parameterPath);
metadataCommand.Syntax.Add(syntax3);
var syntax4 = new MamlSyntax()
@@ -194,6 +219,7 @@ private MamlCommand GetRegenerated()
};
syntax4.Parameters.Add(parameterName1);
+ syntax4.Parameters.Add(parameterPath);
metadataCommand.Syntax.Add(syntax4);
return metadataCommand;
diff --git a/test/Markdown.MAML.Test/Transformer/MamlMultiModelMergerTests.cs b/test/Markdown.MAML.Test/Transformer/MamlMultiModelMergerTests.cs
index 7b8db5b0..47e26d54 100644
--- a/test/Markdown.MAML.Test/Transformer/MamlMultiModelMergerTests.cs
+++ b/test/Markdown.MAML.Test/Transformer/MamlMultiModelMergerTests.cs
@@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Linq;
using Xunit;
+using Markdown.MAML.Model.Markdown;
namespace Markdown.MAML.Test.Transformer
{
@@ -20,7 +21,7 @@ public void Merge3SimpleModels()
var result = merger.Merge(input);
- Assert.Equal(result.Synopsis, @"! First, Second
+ Assert.Equal(result.Synopsis.Text, @"! First, Second
This is the synopsis
@@ -30,9 +31,9 @@ This is the synopsis 3
");
- Assert.Equal(result.Description, "This is a long description.\r\nWith two paragraphs.");
+ Assert.Equal(result.Description.Text, "This is a long description.\r\nWith two paragraphs.");
- Assert.Equal(result.Notes, @"! First
+ Assert.Equal(result.Notes.Text, @"! First
This is a multiline note.
Second line.
@@ -98,9 +99,9 @@ private MamlCommand GetModel1()
MamlCommand command = new MamlCommand()
{
Name = "Get-Foo",
- Synopsis = "This is the synopsis",
- Description = "This is a long description.\r\nWith two paragraphs.",
- Notes = "This is a multiline note.\r\nSecond line.\r\nFirst Command"
+ Synopsis = new SectionBody("This is the synopsis"),
+ Description = new SectionBody("This is a long description.\r\nWith two paragraphs."),
+ Notes = new SectionBody("This is a multiline note.\r\nSecond line.\r\nFirst Command")
};
command.Links.Add(new MamlLink(true)
@@ -154,9 +155,9 @@ private MamlCommand GetModel2()
MamlCommand command = new MamlCommand()
{
Name = "Get-Foo",
- Synopsis = "This is the synopsis",
- Description = "This is a long description.\r\nWith two paragraphs.",
- Notes = "This is a multiline note.\r\nSecond line.\r\nSecond Command"
+ Synopsis = new SectionBody("This is the synopsis"),
+ Description = new SectionBody("This is a long description.\r\nWith two paragraphs."),
+ Notes = new SectionBody("This is a multiline note.\r\nSecond line.\r\nSecond Command")
};
command.Links.Add(new MamlLink(true)
@@ -211,9 +212,9 @@ private MamlCommand GetModel3()
MamlCommand command = new MamlCommand()
{
Name = "Get-Foo",
- Synopsis = "This is the synopsis 3",
- Description = "This is a long description.\r\nWith two paragraphs.",
- Notes = "This is a multiline note.\r\nSecond line.\r\nThird Command"
+ Synopsis = new SectionBody("This is the synopsis 3"),
+ Description = new SectionBody("This is a long description.\r\nWith two paragraphs."),
+ Notes = new SectionBody("This is a multiline note.\r\nSecond line.\r\nThird Command")
};
command.Links.Add(new MamlLink(true)
@@ -338,9 +339,9 @@ private MamlCommand GetModel1()
MamlCommand command = new MamlCommand()
{
Name = "Get-Foo",
- Synopsis = "This is the synopsis",
- Description = "This is a long description.\r\nWith two paragraphs.",
- Notes = "This is a multiline note.\r\nSecond line.\r\nFirst Command"
+ Synopsis = new SectionBody("This is the synopsis"),
+ Description = new SectionBody("This is a long description.\r\nWith two paragraphs."),
+ Notes = new SectionBody("This is a multiline note.\r\nSecond line.\r\nFirst Command")
};
var parameterName = new MamlParameter()
@@ -371,9 +372,9 @@ private MamlCommand GetModel2()
MamlCommand command = new MamlCommand()
{
Name = "Get-Foo",
- Synopsis = "This is the synopsis",
- Description = "This is a long description.\r\nWith two paragraphs.",
- Notes = "This is a multiline note.\r\nSecond line.\r\nSecond Command"
+ Synopsis = new SectionBody("This is the synopsis"),
+ Description = new SectionBody("This is a long description.\r\nWith two paragraphs."),
+ Notes = new SectionBody("This is a multiline note.\r\nSecond line.\r\nSecond Command")
};
var parameterName = new MamlParameter()
diff --git a/test/Markdown.MAML.Test/Transformer/ParserAndTransformerTestsV2.cs b/test/Markdown.MAML.Test/Transformer/ParserAndTransformerTestsV2.cs
index 7acd1030..8dd714b1 100644
--- a/test/Markdown.MAML.Test/Transformer/ParserAndTransformerTestsV2.cs
+++ b/test/Markdown.MAML.Test/Transformer/ParserAndTransformerTestsV2.cs
@@ -20,8 +20,8 @@ public void TransformSimpleCommand()
This is Synopsis
");
MamlCommand mamlCommand = NodeModelToMamlModelV2(doc).First();
- Assert.Equal(mamlCommand.Name, "Get-Foo");
- Assert.Equal(mamlCommand.Synopsis, "This is Synopsis");
+ Assert.Equal("Get-Foo", mamlCommand.Name);
+ Assert.Equal("This is Synopsis", mamlCommand.Synopsis.Text);
}
[Fact]
@@ -34,8 +34,8 @@ public void TransformSynopsisWithHyperlink()
Here is a [hyperlink](http://non-existing-uri).
");
MamlCommand mamlCommand = NodeModelToMamlModelV2(doc).First();
- Assert.Equal(mamlCommand.Name, "Get-Foo");
- Assert.Equal(mamlCommand.Synopsis, "Here is a hyperlink (http://non-existing-uri).");
+ Assert.Equal("Get-Foo", mamlCommand.Name);
+ Assert.Equal("Here is a hyperlink (http://non-existing-uri).", mamlCommand.Synopsis.Text);
}
[Fact]
@@ -54,14 +54,13 @@ public void SkipYamlMetadataBlock()
This is Synopsis
");
MamlCommand mamlCommand = NodeModelToMamlModelV2(doc).First();
- Assert.Equal(mamlCommand.Name, "Get-Foo");
- Assert.Equal(mamlCommand.Synopsis, "This is Synopsis");
+ Assert.Equal("Get-Foo", mamlCommand.Name);
+ Assert.Equal("This is Synopsis", mamlCommand.Synopsis.Text);
}
[Fact]
public void TransformCommandWithExtraLine()
{
-
var doc = ParseString(@"
#Add-Member
@@ -70,8 +69,73 @@ Adds custom properties and methods to an instance of a Windows PowerShell object
");
MamlCommand mamlCommand = NodeModelToMamlModelV2(doc).First();
- Assert.Equal(mamlCommand.Name, "Add-Member");
- Assert.Equal(mamlCommand.Synopsis, "Adds custom properties and methods to an instance of a Windows PowerShell object.");
+ Assert.Equal("Add-Member", mamlCommand.Name);
+ Assert.Equal("Adds custom properties and methods to an instance of a Windows PowerShell object.", mamlCommand.Synopsis.Text);
+ }
+
+ [Fact]
+ public void TransformCommandWithHeaderLineBreak()
+ {
+ var doc = ParseString(@"
+#Add-Member
+
+##SYNOPSIS
+
+Adds custom properties and methods to an instance of a Windows PowerShell object.");
+ MamlCommand mamlCommand = NodeModelToMamlModelV2(doc).First();
+ Assert.Equal("Add-Member", mamlCommand.Name);
+ Assert.Equal("Adds custom properties and methods to an instance of a Windows PowerShell object.", mamlCommand.Synopsis.Text);
+ Assert.Equal(SectionFormatOption.LineBreakAfterHeader, mamlCommand.Synopsis.FormatOption);
+ }
+
+ [Fact]
+ public void TransformCommandWithParameterHeaderLineBreak()
+ {
+ var doc = ParseString(@"
+# Add-Member
+
+## PARAMETERS
+
+### -Name
+
+This is the name parameter.
+
+```yaml
+Type: String
+Parameter Sets: (All)
+Aliases:
+
+Required: True
+Position: 0
+Default value: None
+Accept pipeline input: False
+Accept wildcard characters: False
+```
+");
+ MamlCommand mamlCommand = NodeModelToMamlModelV2(doc).First();
+ Assert.Equal("This is the name parameter.", mamlCommand.Parameters[0].Description);
+ Assert.Equal(SectionFormatOption.LineBreakAfterHeader, mamlCommand.Parameters[0].FormatOption);
+ }
+
+ [Fact]
+ public void TransformCommandWithExampleHeaderLineBreak()
+ {
+ var doc = ParseString(@"
+# Add-Member
+
+## EXAMPLES
+
+### Example 1
+
+This is an example.
+
+```powershell
+PS C:\> Get-PSDocumentHeader -Path '.\build\Default\Server1.md';
+```
+");
+ MamlCommand mamlCommand = NodeModelToMamlModelV2(doc).First();
+ Assert.Equal("This is an example.", mamlCommand.Examples[0].Introduction);
+ Assert.Equal(SectionFormatOption.LineBreakAfterHeader, mamlCommand.Examples[0].FormatOption);
}
[Fact]
@@ -91,7 +155,7 @@ public void TransformMultilineDescription()
And this is my last line.
");
MamlCommand mamlCommand = NodeModelToMamlModelV2(doc).First();
- string[] description = mamlCommand.Description.Split('\n').Select(x => x.Trim()).ToArray();
+ string[] description = mamlCommand.Description.Text.Split('\n').Select(x => x.Trim()).ToArray();
Assert.Equal(3, description.Length);
Assert.Equal("Hello,", description[0]);
Assert.Equal("I'm a multiline description.", description[1]);
@@ -358,49 +422,43 @@ public void ProduceRelatedLinks()
[Fact]
public void HandlesHyperLinksInsideText()
{
-
var doc = ParseString(@"
# Get-Foo
## SYNOPSIS
-
Runs the [Set-WSManQuickConfig]() cmdlet
");
var mamlCommand = NodeModelToMamlModelV2(doc).ToArray();
Assert.Equal(mamlCommand.Count(), 1);
- Assert.Equal(mamlCommand[0].Synopsis, "Runs the Set-WSManQuickConfig cmdlet");
+ Assert.Equal("Runs the Set-WSManQuickConfig cmdlet", mamlCommand[0].Synopsis.Text);
}
[Fact]
public void HandlesItalicInsideText()
{
-
var doc = ParseString(@"
# Get-Foo
## SYNOPSIS
-
Runs the *Set-WSManQuickConfig* cmdlet
");
var mamlCommand = NodeModelToMamlModelV2(doc).ToArray();
Assert.Equal(mamlCommand.Count(), 1);
- Assert.Equal(mamlCommand[0].Synopsis, "Runs the Set-WSManQuickConfig cmdlet");
+ Assert.Equal("Runs the Set-WSManQuickConfig cmdlet", mamlCommand[0].Synopsis.Text);
}
[Fact]
public void HandlesBoldInsideText()
{
-
var doc = ParseString(@"
# Get-Foo
## SYNOPSIS
-
Runs the **Set-WSManQuickConfig** cmdlet
");
var mamlCommand = NodeModelToMamlModelV2(doc).ToArray();
Assert.Equal(mamlCommand.Count(), 1);
- Assert.Equal(mamlCommand[0].Synopsis, "Runs the Set-WSManQuickConfig cmdlet");
+ Assert.Equal("Runs the Set-WSManQuickConfig cmdlet", mamlCommand[0].Synopsis.Text);
}
[Fact]
@@ -504,7 +562,6 @@ public void ProducesParameterEntriesForCornerCases()
## PARAMETERS
### NonExistingTypeParam
-
This is NonExistingTypeParam description.
```yaml
@@ -1014,7 +1071,7 @@ This is intentional.
MamlCommand mamlCommand = NodeModelToMamlModelV2(doc).First();
Assert.Equal("Get-Foo", mamlCommand.Name);
- Assert.Equal(description, mamlCommand.Description);
+ Assert.Equal(description, mamlCommand.Description.Text);
}
private DocumentNode ParseString(string markdown)
diff --git a/test/Pester/PlatyPs.Tests.ps1 b/test/Pester/PlatyPs.Tests.ps1
index 1e6d2ca7..d005a7c3 100644
--- a/test/Pester/PlatyPs.Tests.ps1
+++ b/test/Pester/PlatyPs.Tests.ps1
@@ -606,9 +606,9 @@ Describe 'Get-Help & Get-Command on Add-Computer to build MAML Model Object' {
It 'Validates attributes by checking several sections of the single attributes for Add-Computer' {
$mamlModelObject.Name | Should be "Add-Computer"
- $mamlModelObject.Synopsis | Should be "Add the local computer to a domain or workgroup."
- $mamlModelObject.Description.Substring(0,135) | Should be "The Add-Computer cmdlet adds the local computer or remote computers to a domain or workgroup, or moves them from one domain to another."
- $mamlModelObject.Notes.Substring(0,31) | Should be "In Windows PowerShell 2.0, the "
+ $mamlModelObject.Synopsis.Text | Should be "Add the local computer to a domain or workgroup."
+ $mamlModelObject.Description.Text.Substring(0,135) | Should be "The Add-Computer cmdlet adds the local computer or remote computers to a domain or workgroup, or moves them from one domain to another."
+ $mamlModelObject.Notes.Text.Substring(0,31) | Should be "In Windows PowerShell 2.0, the "
}
It 'Validates the examples by checking Add-Computer Example 1' {