Fix several issues in Markdown cmdlets (#7329)

- Formatting file should be used for `MarkdownOptionInfo` object instead of the types file for adding script property.
- Downlevel windows consoles which do not support VT100 escape sequences should be handled gracefully.
- Add helpuri fwlink for cmdlets.
- Make `-Path` a positional parameter for `ConvertFrom-Markdown`
- make `-InputObject` a positional parameter for `Set-MarkdownOption`
This commit is contained in:
Aditya Patwardhan
2018-07-27 17:26:35 -07:00
committed by Dongbo Wang
parent e7c315b65c
commit 4e7c2ed663
11 changed files with 368 additions and 137 deletions
@@ -21,7 +21,7 @@ namespace Microsoft.PowerShell.Commands
[Cmdlet(
VerbsData.ConvertFrom, "Markdown",
DefaultParameterSetName = PathParameterSet,
HelpUri = "TBD")]
HelpUri = "https://go.microsoft.com/fwlink/?linkid=2006503")]
[OutputType(typeof(Microsoft.PowerShell.MarkdownRender.MarkdownInfo))]
public class ConvertFromMarkdownCommand : PSCmdlet
{
@@ -29,13 +29,14 @@ namespace Microsoft.PowerShell.Commands
/// Gets or sets path to the file to convert from Markdown to MarkdownInfo.
/// </summary>
[ValidateNotNullOrEmpty]
[Parameter(ParameterSetName = PathParameterSet, Mandatory = true)]
[Parameter(ParameterSetName = PathParameterSet, Mandatory = true, Position = 0)]
public string[] Path { get; set; }
/// <summary>
/// Gets or sets the path to the file to convert from Markdown to MarkdownInfo.
/// </summary>
[ValidateNotNullOrEmpty]
[Alias("PSPath", "LP")]
[Parameter(ParameterSetName = LiteralPathParameterSet, Mandatory = true)]
public string[] LiteralPath { get; set; }
@@ -56,20 +57,29 @@ namespace Microsoft.PowerShell.Commands
private const string LiteralPathParameterSet = "LiteralParamSet";
private const string InputObjParamSet = "InputObjParamSet";
private MarkdownConversionType conversionType = MarkdownConversionType.HTML;
private MarkdownOptionInfo mdOption = null;
private PSMarkdownOptionInfo mdOption = null;
/// <summary>
/// Read the MarkdownOptionInfo set in SessionState.
/// Read the PSMarkdownOptionInfo set in SessionState.
/// </summary>
protected override void BeginProcessing()
{
mdOption = SessionState.PSVariable.GetValue("MarkdownOptionInfo", new MarkdownOptionInfo()) as MarkdownOptionInfo;
mdOption = this.CommandInfo.Module.SessionState.PSVariable.GetValue("PSMarkdownOptionInfo", new PSMarkdownOptionInfo()) as PSMarkdownOptionInfo;
if (mdOption == null)
{
throw new InvalidOperationException();
}
bool? supportsVT100 = this.Host?.UI.SupportsVirtualTerminal;
// supportsVT100 == null if the host is null.
// supportsVT100 == false if host does not support VT100.
if (supportsVT100 != true)
{
mdOption.EnableVT100Encoding = false;
}
if (AsVT100EncodedString)
{
conversionType = MarkdownConversionType.VT100;
@@ -122,7 +132,7 @@ namespace Microsoft.PowerShell.Commands
}
}
private void ConvertEachFile(IEnumerable<string> paths, MarkdownConversionType conversionType, bool isLiteral, MarkdownOptionInfo optionInfo)
private void ConvertEachFile(IEnumerable<string> paths, MarkdownConversionType conversionType, bool isLiteral, PSMarkdownOptionInfo optionInfo)
{
foreach (var path in paths)
{
@@ -18,8 +18,8 @@ namespace Microsoft.PowerShell.Commands
[Cmdlet(
VerbsCommon.Set, "MarkdownOption",
DefaultParameterSetName = IndividualSetting,
HelpUri = "TBD")]
[OutputType(typeof(Microsoft.PowerShell.MarkdownRender.MarkdownOptionInfo))]
HelpUri = "https://go.microsoft.com/fwlink/?linkid=2006265")]
[OutputType(typeof(Microsoft.PowerShell.MarkdownRender.PSMarkdownOptionInfo))]
public class SetMarkdownOptionCommand : PSCmdlet
{
/// <summary>
@@ -117,13 +117,13 @@ namespace Microsoft.PowerShell.Commands
/// Gets or sets InputObject.
/// </summary>
[ValidateNotNullOrEmpty]
[Parameter(ParameterSetName = InputObjectParamSet, Mandatory = true, ValueFromPipeline = true)]
[Parameter(ParameterSetName = InputObjectParamSet, Mandatory = true, ValueFromPipeline = true, Position = 0)]
public PSObject InputObject { get; set; }
private const string IndividualSetting = "IndividualSetting";
private const string InputObjectParamSet = "InputObject";
private const string ThemeParamSet = "Theme";
private const string MarkdownOptionInfoVariableName = "MarkdownOptionInfo";
private const string MarkdownOptionInfoVariableName = "PSMarkdownOptionInfo";
private const string LightThemeName = "Light";
private const string DarkThemeName = "Dark";
@@ -132,12 +132,12 @@ namespace Microsoft.PowerShell.Commands
/// </summary>
protected override void EndProcessing()
{
MarkdownOptionInfo mdOptionInfo = null;
PSMarkdownOptionInfo mdOptionInfo = null;
switch (ParameterSetName)
{
case ThemeParamSet:
mdOptionInfo = new MarkdownOptionInfo();
mdOptionInfo = new PSMarkdownOptionInfo();
if (string.Equals(Theme, LightThemeName, StringComparison.OrdinalIgnoreCase))
{
mdOptionInfo.SetLightTheme();
@@ -151,7 +151,7 @@ namespace Microsoft.PowerShell.Commands
case InputObjectParamSet:
object baseObj = InputObject.BaseObject;
mdOptionInfo = baseObj as MarkdownOptionInfo;
mdOptionInfo = baseObj as PSMarkdownOptionInfo;
if (mdOptionInfo == null)
{
@@ -167,13 +167,12 @@ namespace Microsoft.PowerShell.Commands
break;
case IndividualSetting:
mdOptionInfo = new MarkdownOptionInfo();
mdOptionInfo = new PSMarkdownOptionInfo();
SetOptions(mdOptionInfo);
break;
}
var sessionVar = SessionState.PSVariable;
sessionVar.Set(MarkdownOptionInfoVariableName, mdOptionInfo);
this.CommandInfo.Module.SessionState.PSVariable.Set(MarkdownOptionInfoVariableName, mdOptionInfo);
if(PassThru.IsPresent)
{
@@ -181,7 +180,7 @@ namespace Microsoft.PowerShell.Commands
}
}
private void SetOptions(MarkdownOptionInfo mdOptionInfo)
private void SetOptions(PSMarkdownOptionInfo mdOptionInfo)
{
if (!string.IsNullOrEmpty(Header1Color))
{
@@ -245,18 +244,18 @@ namespace Microsoft.PowerShell.Commands
/// </summary>
[Cmdlet(
VerbsCommon.Get, "MarkdownOption",
HelpUri = "TBD")]
[OutputType(typeof(Microsoft.PowerShell.MarkdownRender.MarkdownOptionInfo))]
HelpUri = "https://go.microsoft.com/fwlink/?linkid=2006371")]
[OutputType(typeof(Microsoft.PowerShell.MarkdownRender.PSMarkdownOptionInfo))]
public class GetMarkdownOptionCommand : PSCmdlet
{
private const string MarkdownOptionInfoVariableName = "MarkdownOptionInfo";
private const string MarkdownOptionInfoVariableName = "PSMarkdownOptionInfo";
/// <summary>
/// Override EndProcessing.
/// </summary>
protected override void EndProcessing()
{
WriteObject(SessionState.PSVariable.GetValue(MarkdownOptionInfoVariableName, new MarkdownOptionInfo()));
WriteObject(this.CommandInfo.Module.SessionState.PSVariable.GetValue(MarkdownOptionInfoVariableName, new PSMarkdownOptionInfo()));
}
}
}
@@ -20,7 +20,7 @@ namespace Microsoft.PowerShell.Commands
/// </summary>
[Cmdlet(
VerbsCommon.Show, "Markdown",
HelpUri = "TBD")]
HelpUri = "https://go.microsoft.com/fwlink/?linkid=2006266")]
[OutputType(typeof(string))]
public class ShowMarkdownCommand : PSCmdlet
{
@@ -59,7 +59,7 @@ namespace Microsoft.PowerShell.MarkdownRender
/// <param name="conversionType">Specifies type of conversion, either VT100 or HTML.</param>
/// <param name="optionInfo">Specifies the rendering options for VT100 rendering.</param>
/// <returns>MarkdownInfo object with the converted output.</returns>
public static MarkdownInfo Convert(string markdownString, MarkdownConversionType conversionType, MarkdownOptionInfo optionInfo)
public static MarkdownInfo Convert(string markdownString, MarkdownConversionType conversionType, PSMarkdownOptionInfo optionInfo)
{
var renderInfo = new MarkdownInfo();
var writer = new StringWriter();
@@ -8,6 +8,7 @@
<ItemGroup>
<!-- Source: https://github.com/lunet-io/markdig/ -->
<ProjectReference Include="../System.Management.Automation/System.Management.Automation.csproj" />
<PackageReference Include="Markdig.Signed" Version="0.15.1" />
</ItemGroup>
@@ -3,6 +3,7 @@
using System;
using System.IO;
using System.Management.Automation;
using Markdig;
using Markdig.Renderers;
using Markdig.Syntax;
@@ -10,7 +11,7 @@ using Markdig.Syntax;
namespace Microsoft.PowerShell.MarkdownRender
{
/// <summary>
/// Enum to name all the properties of MarkdownOptionInfo.
/// Enum to name all the properties of PSMarkdownOptionInfo.
/// </summary>
public enum MarkdownOptionInfoProperty
{
@@ -73,7 +74,7 @@ namespace Microsoft.PowerShell.MarkdownRender
/// <summary>
/// Class to represent color preference options for various Markdown elements.
/// </summary>
public sealed class MarkdownOptionInfo
public sealed class PSMarkdownOptionInfo
{
private const char Esc = (char)0x1b;
private const string EndSequence = "[0m";
@@ -133,9 +134,14 @@ namespace Microsoft.PowerShell.MarkdownRender
/// </summary>
public string EmphasisItalics { get; set; }
/// <summary>
/// Gets or sets a value indicating whether VT100 escape sequences should be added. Default it true.
/// </summary>
public bool EnableVT100Encoding { get; set; }
/// <summary>
/// Get the property as an rendered escape sequence.
/// This is used for typesps1xml for displaying.
/// This is used by formatting system for displaying.
/// </summary>
/// <param name="propertyName">Name of the property to get as escape sequence.</param>
/// <returns>Specified property name as escape sequence.</returns>
@@ -184,11 +190,12 @@ namespace Microsoft.PowerShell.MarkdownRender
}
/// <summary>
/// Initializes a new instance of <see cref="MarkdownOptionInfo"/> class and sets dark as the default theme.
/// Initializes a new instance of the <see cref="PSMarkdownOptionInfo"/> class and sets dark as the default theme.
/// </summary>
public MarkdownOptionInfo()
public PSMarkdownOptionInfo()
{
SetDarkTheme();
EnableVT100Encoding = true;
}
private const string Header1Dark = "[7m";
@@ -198,6 +205,7 @@ namespace Microsoft.PowerShell.MarkdownRender
private const string Header5Dark = "[4;96m";
private const string Header6Dark = "[4;97m";
private const string CodeDark = "[48;2;155;155;155;38;2;30;30;30m";
private const string CodeMacOS = "[107;95m";
private const string LinkDark = "[4;38;5;117m";
private const string ImageDark = "[33m";
private const string EmphasisBoldDark = "[1m";
@@ -226,11 +234,11 @@ namespace Microsoft.PowerShell.MarkdownRender
Header4 = Header4Dark;
Header5 = Header5Dark;
Header6 = Header6Dark;
Code = CodeDark;
Link = LinkDark;
Image = ImageDark;
EmphasisBold = EmphasisBoldDark;
EmphasisItalics = EmphasisItalicsDark;
SetCodeColor(isDarkTheme: true);
}
/// <summary>
@@ -244,11 +252,17 @@ namespace Microsoft.PowerShell.MarkdownRender
Header4 = Header4Light;
Header5 = Header5Light;
Header6 = Header6Light;
Code = CodeLight;
Link = LinkLight;
Image = ImageLight;
EmphasisBold = EmphasisBoldLight;
EmphasisItalics = EmphasisItalicsLight;
SetCodeColor(isDarkTheme: false);
}
private void SetCodeColor(bool isDarkTheme)
{
// MacOS terminal app does not support extended colors for VT100, so we special case for it.
Code = Platform.IsMacOS ? CodeMacOS : isDarkTheme ? CodeDark : CodeLight;
}
}
@@ -262,13 +276,13 @@ namespace Microsoft.PowerShell.MarkdownRender
// For code blocks, [500@ make sure that the whole line has background color.
private const string LongBackgroundCodeBlock = "[500@";
private MarkdownOptionInfo options;
private PSMarkdownOptionInfo options;
/// <summary>
/// Initializes a new instance of the <see cref="VT100EscapeSequences"/> class.
/// </summary>
/// <param name="optionInfo">MarkdownOptionInfo object to initialize with.</param>
public VT100EscapeSequences(MarkdownOptionInfo optionInfo)
/// <param name="optionInfo">PSMarkdownOptionInfo object to initialize with.</param>
public VT100EscapeSequences(PSMarkdownOptionInfo optionInfo)
{
if (optionInfo == null)
{
@@ -285,7 +299,7 @@ namespace Microsoft.PowerShell.MarkdownRender
/// <returns>Formatted Header 1 string.</returns>
public string FormatHeader1(string headerText)
{
return string.Concat(Esc, options.Header1, headerText, endSequence);
return FormatHeader(headerText, options.Header1);
}
/// <summary>
@@ -295,7 +309,7 @@ namespace Microsoft.PowerShell.MarkdownRender
/// <returns>Formatted Header 2 string.</returns>
public string FormatHeader2(string headerText)
{
return string.Concat(Esc, options.Header2, headerText, endSequence);
return FormatHeader(headerText, options.Header2);
}
/// <summary>
@@ -305,7 +319,7 @@ namespace Microsoft.PowerShell.MarkdownRender
/// <returns>Formatted Header 3 string.</returns>
public string FormatHeader3(string headerText)
{
return string.Concat(Esc, options.Header3, headerText, endSequence);
return FormatHeader(headerText, options.Header3);
}
/// <summary>
@@ -315,7 +329,7 @@ namespace Microsoft.PowerShell.MarkdownRender
/// <returns>Formatted Header 4 string.</returns>
public string FormatHeader4(string headerText)
{
return string.Concat(Esc, options.Header4, headerText, endSequence);
return FormatHeader(headerText, options.Header4);
}
/// <summary>
@@ -325,7 +339,7 @@ namespace Microsoft.PowerShell.MarkdownRender
/// <returns>Formatted Header 5 string.</returns>
public string FormatHeader5(string headerText)
{
return string.Concat(Esc, options.Header5, headerText, endSequence);
return FormatHeader(headerText, options.Header5);
}
/// <summary>
@@ -335,7 +349,7 @@ namespace Microsoft.PowerShell.MarkdownRender
/// <returns>Formatted Header 6 string.</returns>
public string FormatHeader6(string headerText)
{
return string.Concat(Esc, options.Header6, headerText, endSequence);
return FormatHeader(headerText, options.Header6);
}
/// <summary>
@@ -346,13 +360,29 @@ namespace Microsoft.PowerShell.MarkdownRender
/// <returns>Formatted code block string.</returns>
public string FormatCode(string codeText, bool isInline)
{
bool isVT100Enabled = options.EnableVT100Encoding;
if (isInline)
{
return string.Concat(Esc, options.Code, codeText, endSequence);
if (isVT100Enabled)
{
return string.Concat(Esc, options.Code, codeText, endSequence);
}
else
{
return codeText;
}
}
else
{
return string.Concat(Esc, options.Code, codeText, Esc, LongBackgroundCodeBlock, endSequence);
if (isVT100Enabled)
{
return string.Concat(Esc, options.Code, codeText, Esc, LongBackgroundCodeBlock, endSequence);
}
else
{
return codeText;
}
}
}
@@ -365,13 +395,29 @@ namespace Microsoft.PowerShell.MarkdownRender
/// <returns>Formatted link string.</returns>
public string FormatLink(string linkText, string url, bool hideUrl = true)
{
bool isVT100Enabled = options.EnableVT100Encoding;
if (hideUrl)
{
return string.Concat(Esc, options.Link, "\"", linkText, "\"", endSequence);
if (isVT100Enabled)
{
return string.Concat(Esc, options.Link, "\"", linkText, "\"", endSequence);
}
else
{
return string.Concat("\"", linkText, "\"");
}
}
else
{
return string.Concat("\"", linkText, "\" (", Esc, options.Link, url, endSequence, ")");
if (isVT100Enabled)
{
return string.Concat("\"", linkText, "\" (", Esc, options.Link, url, endSequence, ")");
}
else
{
return string.Concat("\"", linkText, "\" (", url, ")");
}
}
}
@@ -384,7 +430,15 @@ namespace Microsoft.PowerShell.MarkdownRender
public string FormatEmphasis(string emphasisText, bool isBold)
{
var sequence = isBold ? options.EmphasisBold : options.EmphasisItalics;
return string.Concat(Esc, sequence, emphasisText, endSequence);
if (options.EnableVT100Encoding)
{
return string.Concat(Esc, sequence, emphasisText, endSequence);
}
else
{
return emphasisText;
}
}
/// <summary>
@@ -401,7 +455,26 @@ namespace Microsoft.PowerShell.MarkdownRender
text = "Image";
}
return string.Concat(Esc, options.Image, "[", text, "]", endSequence);
if (options.EnableVT100Encoding)
{
return string.Concat(Esc, options.Image, "[", text, "]", endSequence);
}
else
{
return string.Concat("[", text, "]");
}
}
private string FormatHeader(string headerText, string headerEscapeSequence)
{
if (options.EnableVT100Encoding)
{
return string.Concat(Esc, headerEscapeSequence, headerText, endSequence);
}
else
{
return headerText;
}
}
}
}
@@ -18,8 +18,8 @@ namespace Microsoft.PowerShell.MarkdownRender
/// Initializes a new instance of the <see cref="VT100Renderer"/> class.
/// </summary>
/// <param name="writer">TextWriter to write to.</param>
/// <param name="optionInfo">MarkdownOptionInfo object with options.</param>
public VT100Renderer(TextWriter writer, MarkdownOptionInfo optionInfo) : base(writer)
/// <param name="optionInfo">PSMarkdownOptionInfo object with options.</param>
public VT100Renderer(TextWriter writer, PSMarkdownOptionInfo optionInfo) : base(writer)
{
EscapeSequences = new VT100EscapeSequences(optionInfo);
@@ -250,6 +250,10 @@ namespace System.Management.Automation.Runspaces
yield return new ExtendedTypeDefinition(
"Microsoft.PowerShell.Commands.PSRunspaceDebug",
ViewsOf_Microsoft_PowerShell_Commands_PSRunspaceDebug());
yield return new ExtendedTypeDefinition(
"Microsoft.PowerShell.MarkdownRender.PSMarkdownOptionInfo",
ViewsOf_Microsoft_PowerShell_MarkdownRender_MarkdownOptionInfo());
}
private static IEnumerable<FormatViewDefinition> ViewsOf_System_RuntimeType()
@@ -1365,5 +1369,25 @@ namespace System.Management.Automation.Runspaces
.EndRowDefinition()
.EndTable());
}
private static IEnumerable<FormatViewDefinition> ViewsOf_Microsoft_PowerShell_MarkdownRender_MarkdownOptionInfo()
{
yield return new FormatViewDefinition("Microsoft.PowerShell.MarkdownRender.PSMarkdownOptionInfo",
ListControl.Create()
.StartEntry()
.AddItemScriptBlock(@"$_.AsEscapeSequence('Header1')", label: "Header1")
.AddItemScriptBlock(@"$_.AsEscapeSequence('Header2')", label: "Header2")
.AddItemScriptBlock(@"$_.AsEscapeSequence('Header3')", label: "Header3")
.AddItemScriptBlock(@"$_.AsEscapeSequence('Header4')", label: "Header4")
.AddItemScriptBlock(@"$_.AsEscapeSequence('Header5')", label: "Header5")
.AddItemScriptBlock(@"$_.AsEscapeSequence('Header6')", label: "Header6")
.AddItemScriptBlock(@"$_.AsEscapeSequence('Code')", label: "Code")
.AddItemScriptBlock(@"$_.AsEscapeSequence('Link')", label: "Link")
.AddItemScriptBlock(@"$_.AsEscapeSequence('Image')", label: "Image")
.AddItemScriptBlock(@"$_.AsEscapeSequence('EmphasisBold')", label: "EmphasisBold")
.AddItemScriptBlock(@"$_.AsEscapeSequence('EmphasisItalics')", label: "EmphasisItalics")
.EndEntry()
.EndList());
}
}
}
@@ -114,31 +114,6 @@ namespace System.Management.Automation.Runspaces
var td15 = new TypeData(@"Deserialized.System.Management.Automation.DebuggerStopEventArgs", true);
td15.TargetTypeForDeserialization = typeof(Microsoft.PowerShell.DeserializingTypeConverter);
yield return td15;
var td16 = new TypeData(@"Microsoft.PowerShell.MarkdownRender.MarkdownOptionInfo");
td16.Members.Add("Header1",
new ScriptPropertyData(@"Header1", GetScriptBlock(@"$this.AsEscapeSequence('Header1')"), setScriptBlock: null));
td16.Members.Add("Header2",
new ScriptPropertyData(@"Header2", GetScriptBlock(@"$this.AsEscapeSequence('Header2')"), setScriptBlock: null));
td16.Members.Add("Header3",
new ScriptPropertyData(@"Header3", GetScriptBlock(@"$this.AsEscapeSequence('Header3')"), setScriptBlock: null));
td16.Members.Add("Header4",
new ScriptPropertyData(@"Header4", GetScriptBlock(@"$this.AsEscapeSequence('Header4')"), setScriptBlock: null));
td16.Members.Add("Header5",
new ScriptPropertyData(@"Header5", GetScriptBlock(@"$this.AsEscapeSequence('Header5')"), setScriptBlock: null));
td16.Members.Add("Header6",
new ScriptPropertyData(@"Header6", GetScriptBlock(@"$this.AsEscapeSequence('Header6')"), setScriptBlock: null));
td16.Members.Add("Code",
new ScriptPropertyData(@"Code", GetScriptBlock(@"$this.AsEscapeSequence('Code')"), setScriptBlock: null));
td16.Members.Add("Link",
new ScriptPropertyData(@"Link", GetScriptBlock(@"$this.AsEscapeSequence('Link')"), setScriptBlock: null));
td16.Members.Add("Image",
new ScriptPropertyData(@"Image", GetScriptBlock(@"$this.AsEscapeSequence('Image')"), setScriptBlock: null));
td16.Members.Add("EmphasisBold",
new ScriptPropertyData(@"EmphasisBold", GetScriptBlock(@"$this.AsEscapeSequence('EmphasisBold')"), setScriptBlock: null));
td16.Members.Add("EmphasisItalics",
new ScriptPropertyData(@"EmphasisItalics", GetScriptBlock(@"$this.AsEscapeSequence('EmphasisItalics')"), setScriptBlock: null));
yield return td16;
}
}
}
@@ -22,30 +22,59 @@ Describe 'ConvertFrom-Markdown tests' -Tags 'CI' {
[string] $CodeFormatString,
[string] $CodeText
[string] $CodeText,
[bool] $VT100Support
)
switch($elementType)
{
"Header1" { "$esc[7m$text$esc[0m`n`n" }
"Header2" { "$esc[4;93m$text$esc[0m`n`n" }
"Header3" { "$esc[4;94m$text$esc[0m`n`n" }
"Header4" { "$esc[4;95m$text$esc[0m`n`n" }
"Header5" { "$esc[4;96m$text$esc[0m`n`n" }
"Header6" { "$esc[4;97m$text$esc[0m`n`n" }
"Header1" { if($VT100Support) {"$esc[7m$text$esc[0m`n`n" } else {"$text`n`n"} }
"Header2" { if($VT100Support) {"$esc[4;93m$text$esc[0m`n`n" } else {"$text`n`n"} }
"Header3" { if($VT100Support) {"$esc[4;94m$text$esc[0m`n`n" } else {"$text`n`n"} }
"Header4" { if($VT100Support) {"$esc[4;95m$text$esc[0m`n`n" } else {"$text`n`n"} }
"Header5" { if($VT100Support) {"$esc[4;96m$text$esc[0m`n`n" } else {"$text`n`n"} }
"Header6" { if($VT100Support) {"$esc[4;97m$text$esc[0m`n`n" } else {"$text`n`n"} }
"Code" { ($CodeFormatString -f "$esc[48;2;155;155;155;38;2;30;30;30m$CodeText$esc[0m") + "`n`n" }
"Code" {
if($VT100Support) {
if($IsMacOS)
{
($CodeFormatString -f "$esc[107;95m$CodeText$esc[0m") + "`n`n"
}
else
{
($CodeFormatString -f "$esc[48;2;155;155;155;38;2;30;30;30m$CodeText$esc[0m") + "`n`n"
}
}
else {
$CodeFormatString -f "$CodeText" + "`n`n"
}
}
"CodeBlock" {
$expectedString = @()
$CodeText -split "`n" | ForEach-Object { $expectedString += "$esc[48;2;155;155;155;38;2;30;30;30m$_$esc[500@$esc[0m" }
$CodeText -split "`n" | ForEach-Object {
if($VT100Support) {
if($IsMacOS) {
$expectedString += "$esc[107;95m$_$esc[500@$esc[0m"
}
else {
$expectedString += "$esc[48;2;155;155;155;38;2;30;30;30m$_$esc[500@$esc[0m"
}
}
else {
$expectedString += $_
}
}
$returnString = $expectedString -join "`n"
"$returnString`n`n"
}
"Link" { "$esc[4;38;5;117m`"$text`"$esc[0m`n" }
"Image" { "$esc[33m[$text]$esc[0m`n" }
"Bold" { "$esc[1m$text$esc[0m`n" }
"Italics" { "$esc[36m$text$esc[0m`n" }
"Link" { if($VT100Support) {"$esc[4;38;5;117m`"$text`"$esc[0m`n" } else { "`"$text`"`n" } }
"Image" { if($VT100Support) { "$esc[33m[$text]$esc[0m`n" } else { "[$text]`n" } }
"Bold" { if($VT100Support) { "$esc[1m$text$esc[0m`n" } else { "$text`n" } }
"Italics" { if($VT100Support) { "$esc[36m$text$esc[0m`n" } else { "$text`n" } }
}
}
@@ -112,26 +141,54 @@ bool function()`n{`n}
"@
$TestCases = @(
@{ element = 'Header1'; InputMD = '# Header 1'; Text = 'Header 1' }
@{ element = 'Header2'; InputMD = '## Header 2'; Text = 'Header 2' }
@{ element = 'Header3'; InputMD = '### Header 3'; Text = 'Header 3' }
@{ element = 'Header4'; InputMD = '#### Header 4'; Text = 'Header 4' }
@{ element = 'Header5'; InputMD = '##### Header 5'; Text = 'Header 5' }
@{ element = 'Header6'; InputMD = '###### Header 6'; Text = 'Header 6' }
@{ element = 'Code'; InputMD = 'This is a `code` sample'; CodeFormatString = 'This is a {0} sample'; CodeText = 'code'}
@{ element = 'CodeBlock'; InputMD = $codeBlock; CodeText = $codeBlockText }
@{ element = 'Link'; InputMD = '[GitHub](https://www.github.com)'; Text = 'GitHub'; Url = 'https://www.github.com'}
@{ element = 'Image'; InputMD = '![alt-text](https://bing.com/ps.svg)'; Text = 'alt-text'; Url = 'https://bing.com/ps.svg'}
@{ element = 'Bold'; InputMD = '**bold text**'; Text = 'bold text' }
@{ element = 'Italics'; InputMD = '*italics text*'; Text = 'italics text' }
@{ element = 'Header1'; InputMD = '# Header 1'; Text = 'Header 1'; VT100 = $true }
@{ element = 'Header2'; InputMD = '## Header 2'; Text = 'Header 2'; VT100 = $true }
@{ element = 'Header3'; InputMD = '### Header 3'; Text = 'Header 3'; VT100 = $true }
@{ element = 'Header4'; InputMD = '#### Header 4'; Text = 'Header 4'; VT100 = $true }
@{ element = 'Header5'; InputMD = '##### Header 5'; Text = 'Header 5'; VT100 = $true }
@{ element = 'Header6'; InputMD = '###### Header 6'; Text = 'Header 6'; VT100 = $true }
@{ element = 'Code'; InputMD = 'This is a `code` sample'; CodeFormatString = 'This is a {0} sample'; CodeText = 'code'; VT100 = $true}
@{ element = 'CodeBlock'; InputMD = $codeBlock; CodeText = $codeBlockText; VT100 = $true }
@{ element = 'Link'; InputMD = '[GitHub](https://www.github.com)'; Text = 'GitHub'; Url = 'https://www.github.com'; VT100 = $true}
@{ element = 'Image'; InputMD = '![alt-text](https://bing.com/ps.svg)'; Text = 'alt-text'; Url = 'https://bing.com/ps.svg'; VT100 = $true}
@{ element = 'Bold'; InputMD = '**bold text**'; Text = 'bold text'; VT100 = $true}
@{ element = 'Italics'; InputMD = '*italics text*'; Text = 'italics text'; VT100 = $true }
@{ element = 'Header1'; InputMD = '# Header 1'; Text = 'Header 1'; VT100 = $false }
@{ element = 'Header2'; InputMD = '## Header 2'; Text = 'Header 2'; VT100 = $false }
@{ element = 'Header3'; InputMD = '### Header 3'; Text = 'Header 3'; VT100 = $false }
@{ element = 'Header4'; InputMD = '#### Header 4'; Text = 'Header 4'; VT100 = $false }
@{ element = 'Header5'; InputMD = '##### Header 5'; Text = 'Header 5'; VT100 = $false }
@{ element = 'Header6'; InputMD = '###### Header 6'; Text = 'Header 6'; VT100 = $false }
@{ element = 'Code'; InputMD = 'This is a `code` sample'; CodeFormatString = 'This is a {0} sample'; CodeText = 'code'; VT100 = $false}
@{ element = 'CodeBlock'; InputMD = $codeBlock; CodeText = $codeBlockText ; VT100 = $false}
@{ element = 'Link'; InputMD = '[GitHub](https://www.github.com)'; Text = 'GitHub'; Url = 'https://www.github.com'; VT100 = $false}
@{ element = 'Image'; InputMD = '![alt-text](https://bing.com/ps.svg)'; Text = 'alt-text'; Url = 'https://bing.com/ps.svg'; VT100 = $false}
@{ element = 'Bold'; InputMD = '**bold text**'; Text = 'bold text' ; VT100 = $false}
@{ element = 'Italics'; InputMD = '*italics text*'; Text = 'italics text' ; VT100 = $false}
)
}
It 'Can convert element : <element> to vt100 using pipeline input - VT100 : <VT100>' -TestCases $TestCases {
param($element, $inputMD, $text, $codeFormatString, $codeText, $VT100)
It 'Can convert element : <element> to vt100 using pipeline input' -TestCases $TestCases {
param($element, $inputMD, $text, $codeFormatString, $codeText)
try
{
if(-not $VT100)
{
$options = Get-MarkdownOption
$options.EnableVT100Encoding = $false
$options | Set-MarkdownOption
}
$output = $inputMD | ConvertFrom-Markdown -AsVT100EncodedString
$output = $inputMD | ConvertFrom-Markdown -AsVT100EncodedString
}
finally
{
$options = Get-MarkdownOption
$options.EnableVT100Encoding = $true
$options | Set-MarkdownOption
}
if($element -like 'Header?' -or
$element -eq 'Link' -or
@@ -139,15 +196,15 @@ bool function()`n{`n}
$element -eq 'Bold' -or
$element -eq 'Italics')
{
$expectedString = GetExpectedString -ElementType $element -Text $text
$expectedString = GetExpectedString -ElementType $element -Text $text -VT100Support $VT100
}
elseif($element -eq 'Code')
{
$expectedString = GetExpectedString -ElementType $element -CodeFormatString $codeFormatString -CodeText $codeText
$expectedString = GetExpectedString -ElementType $element -CodeFormatString $codeFormatString -CodeText $codeText -VT100Support $VT100
}
elseif($element -eq 'CodeBlock')
{
$expectedString = GetExpectedString -ElementType $element -CodeText $codeText
$expectedString = GetExpectedString -ElementType $element -CodeText $codeText -VT100Support $VT100
}
$output.VT100EncodedString | Should -BeExactly $expectedString
@@ -198,6 +255,11 @@ bool function()`n{`n}
$output = ConvertFrom-Markdown -Path $mdLiteralPath -AsVT100EncodedString
$output.VT100EncodedString | Should -BeExactly $expectedStringFromFile
}
It 'Can accept Path as positional parameter' {
$output = ConvertFrom-Markdown $mdFile.FullName -AsVT100EncodedString
$output.VT100EncodedString | Should -BeExactly $expectedStringFromFile
}
}
Context "ConvertFrom-Markdown error cases" {
@@ -235,17 +297,26 @@ bool function()`n{`n}
It "Verify default values for MarkdownOptions" {
$options = Get-MarkdownOption
$options.Header1 | Should -BeExactly "$esc[7m[7m$esc[0m"
$options.Header2 | Should -BeExactly "$esc[4;93m[4;93m$esc[0m"
$options.Header3 | Should -BeExactly "$esc[4;94m[4;94m$esc[0m"
$options.Header4 | Should -BeExactly "$esc[4;95m[4;95m$esc[0m"
$options.Header5 | Should -BeExactly "$esc[4;96m[4;96m$esc[0m"
$options.Header6 | Should -BeExactly "$esc[4;97m[4;97m$esc[0m"
$options.Code | Should -BeExactly "$esc[48;2;155;155;155;38;2;30;30;30m[48;2;155;155;155;38;2;30;30;30m$esc[0m"
$options.Link | Should -BeExactly "$esc[4;38;5;117m[4;38;5;117m$esc[0m"
$options.Image | Should -BeExactly "$esc[33m[33m$esc[0m"
$options.EmphasisBold | Should -BeExactly "$esc[1m[1m$esc[0m"
$options.EmphasisItalics | Should -BeExactly "$esc[36m[36m$esc[0m"
$options.AsEscapeSequence("Header1") | Should -BeExactly "$esc[7m[7m$esc[0m"
$options.AsEscapeSequence("Header2") | Should -BeExactly "$esc[4;93m[4;93m$esc[0m"
$options.AsEscapeSequence("Header3") | Should -BeExactly "$esc[4;94m[4;94m$esc[0m"
$options.AsEscapeSequence("Header4") | Should -BeExactly "$esc[4;95m[4;95m$esc[0m"
$options.AsEscapeSequence("Header5") | Should -BeExactly "$esc[4;96m[4;96m$esc[0m"
$options.AsEscapeSequence("Header6") | Should -BeExactly "$esc[4;97m[4;97m$esc[0m"
if($IsMacOS)
{
$options.AsEscapeSequence("Code") | Should -BeExactly "$esc[107;95m[107;95m$esc[0m"
}
else
{
$options.AsEscapeSequence("Code") | Should -BeExactly "$esc[48;2;155;155;155;38;2;30;30;30m[48;2;155;155;155;38;2;30;30;30m$esc[0m"
}
$options.AsEscapeSequence("Link") | Should -BeExactly "$esc[4;38;5;117m[4;38;5;117m$esc[0m"
$options.AsEscapeSequence("Image") | Should -BeExactly "$esc[33m[33m$esc[0m"
$options.AsEscapeSequence("EmphasisBold") | Should -BeExactly "$esc[1m[1m$esc[0m"
$options.AsEscapeSequence("EmphasisItalics") | Should -BeExactly "$esc[36m[36m$esc[0m"
}
It "Verify Set-MarkdownOption can get options" {
@@ -263,34 +334,108 @@ bool function()`n{`n}
$newOptions = Get-MarkdownOption
$newOptions.Header1 | Should -BeExactly "$esc[4;1m[4;1m$esc[0m"
$newOptions.Header2 | Should -BeExactly "$esc[93m[93m$esc[0m"
$newOptions.Header3 | Should -BeExactly "$esc[94m[94m$esc[0m"
$newOptions.Header4 | Should -BeExactly "$esc[95m[95m$esc[0m"
$newOptions.Header5 | Should -BeExactly "$esc[96m[96m$esc[0m"
$newOptions.Header6 | Should -BeExactly "$esc[97m[97m$esc[0m"
#$options.Code | Should -BeExactly "$esc[48;2;155;155;155;38;2;30;30;30m[48;2;155;155;155;38;2;30;30;30m$esc[0m"
$newOptions.Link | Should -BeExactly "$esc[4;38;5;88m[4;38;5;88m$esc[0m"
$newOptions.Image | Should -BeExactly "$esc[34m[34m$esc[0m"
$newOptions.EmphasisBold | Should -BeExactly "$esc[32m[32m$esc[0m"
$newOptions.EmphasisItalics | Should -BeExactly "$esc[35m[35m$esc[0m"
$newOptions.AsEscapeSequence("Header1") | Should -BeExactly "$esc[4;1m[4;1m$esc[0m"
$newOptions.AsEscapeSequence("Header2") | Should -BeExactly "$esc[93m[93m$esc[0m"
$newOptions.AsEscapeSequence("Header3") | Should -BeExactly "$esc[94m[94m$esc[0m"
$newOptions.AsEscapeSequence("Header4") | Should -BeExactly "$esc[95m[95m$esc[0m"
$newOptions.AsEscapeSequence("Header5") | Should -BeExactly "$esc[96m[96m$esc[0m"
$newOptions.AsEscapeSequence("Header6") | Should -BeExactly "$esc[97m[97m$esc[0m"
if($IsMacOS)
{
$newOptions.AsEscapeSequence("Code") | Should -BeExactly "$esc[107;95m[107;95m$esc[0m"
}
else
{
$newOptions.AsEscapeSequence("Code") | Should -BeExactly "$esc[48;2;155;155;155;38;2;30;30;30m[48;2;155;155;155;38;2;30;30;30m$esc[0m"
}
$newOptions.AsEscapeSequence("Link") | Should -BeExactly "$esc[4;38;5;88m[4;38;5;88m$esc[0m"
$newOptions.AsEscapeSequence("Image") | Should -BeExactly "$esc[34m[34m$esc[0m"
$newOptions.AsEscapeSequence("EmphasisBold") | Should -BeExactly "$esc[32m[32m$esc[0m"
$newOptions.AsEscapeSequence("EmphasisItalics") | Should -BeExactly "$esc[35m[35m$esc[0m"
}
It "Verify defaults for light theme" {
Set-MarkdownOption -Theme Light
$options = Get-MarkdownOption
$options.Header1 | Should -BeExactly "$esc[7m[7m$esc[0m"
$options.Header2 | Should -BeExactly "$esc[4;33m[4;33m$esc[0m"
$options.Header3 | Should -BeExactly "$esc[4;34m[4;34m$esc[0m"
$options.Header4 | Should -BeExactly "$esc[4;35m[4;35m$esc[0m"
$options.Header5 | Should -BeExactly "$esc[4;36m[4;36m$esc[0m"
$options.Header6 | Should -BeExactly "$esc[4;30m[4;30m$esc[0m"
$options.Code | Should -BeExactly "$esc[48;2;155;155;155;38;2;30;30;30m[48;2;155;155;155;38;2;30;30;30m$esc[0m"
$options.Link | Should -BeExactly "$esc[4;38;5;117m[4;38;5;117m$esc[0m"
$options.Image | Should -BeExactly "$esc[33m[33m$esc[0m"
$options.EmphasisBold | Should -BeExactly "$esc[1m[1m$esc[0m"
$options.EmphasisItalics | Should -BeExactly "$esc[36m[36m$esc[0m"
$options.AsEscapeSequence("Header1") | Should -BeExactly "$esc[7m[7m$esc[0m"
$options.AsEscapeSequence("Header2") | Should -BeExactly "$esc[4;33m[4;33m$esc[0m"
$options.AsEscapeSequence("Header3") | Should -BeExactly "$esc[4;34m[4;34m$esc[0m"
$options.AsEscapeSequence("Header4") | Should -BeExactly "$esc[4;35m[4;35m$esc[0m"
$options.AsEscapeSequence("Header5") | Should -BeExactly "$esc[4;36m[4;36m$esc[0m"
$options.AsEscapeSequence("Header6") | Should -BeExactly "$esc[4;30m[4;30m$esc[0m"
if($IsMacOS)
{
$options.AsEscapeSequence("Code") | Should -BeExactly "$esc[107;95m[107;95m$esc[0m"
}
else
{
$options.AsEscapeSequence("Code") | Should -BeExactly "$esc[48;2;155;155;155;38;2;30;30;30m[48;2;155;155;155;38;2;30;30;30m$esc[0m"
}
$options.AsEscapeSequence("Link") | Should -BeExactly "$esc[4;38;5;117m[4;38;5;117m$esc[0m"
$options.AsEscapeSequence("Image") | Should -BeExactly "$esc[33m[33m$esc[0m"
$options.AsEscapeSequence("EmphasisBold") | Should -BeExactly "$esc[1m[1m$esc[0m"
$options.AsEscapeSequence("EmphasisItalics") | Should -BeExactly "$esc[36m[36m$esc[0m"
}
It "Options should be string without escape sequences" {
$options = Get-MarkdownOption
$options.Header1 | Should -BeExactly "[7m"
$options.Header2 | Should -BeExactly "[4;93m"
$options.Header3 | Should -BeExactly "[4;94m"
$options.Header4 | Should -BeExactly "[4;95m"
$options.Header5 | Should -BeExactly "[4;96m"
$options.Header6 | Should -BeExactly "[4;97m"
if($IsMacOS)
{
$options.Code | Should -BeExactly "[107;95m"
}
else
{
$options.Code | Should -BeExactly "[48;2;155;155;155;38;2;30;30;30m"
}
$options.Link | Should -BeExactly "[4;38;5;117m"
$options.Image | Should -BeExactly "[33m"
$options.EmphasisBold | Should -BeExactly "[1m"
$options.EmphasisItalics | Should -BeExactly "[36m"
}
It "Verify PSMarkdownOptionInfo is defined in module scope" {
$PSMarkdownOptionInfo | Should -BeNullOrEmpty
$mod = Get-Module Microsoft.PowerShell.Utility
$options = & $mod { $PSMarkdownOptionInfo }
$options.Header1 | Should -BeExactly "[7m"
$options.Header2 | Should -BeExactly "[4;93m"
$options.Header3 | Should -BeExactly "[4;94m"
$options.Header4 | Should -BeExactly "[4;95m"
$options.Header5 | Should -BeExactly "[4;96m"
$options.Header6 | Should -BeExactly "[4;97m"
if($IsMacOS)
{
$options.Code | Should -BeExactly "[107;95m"
}
else
{
$options.Code | Should -BeExactly "[48;2;155;155;155;38;2;30;30;30m"
}
$options.Link | Should -BeExactly "[4;38;5;117m"
$options.Image | Should -BeExactly "[33m"
$options.EmphasisBold | Should -BeExactly "[1m"
$options.EmphasisItalics | Should -BeExactly "[36m"
}
}
@@ -306,7 +451,7 @@ bool function()`n{`n}
It "can show VT100 converted from markdown" {
$text = "Bold"
$mdText = "**$text**"
$expectedString = GetExpectedString -ElementType 'Bold' -Text $text
$expectedString = GetExpectedString -ElementType 'Bold' -Text $text -VT100Support $true
$result = $mdText | ConvertFrom-Markdown -AsVT100EncodedString | Show-Markdown
$result | Should -BeExactly $expectedString
@@ -91,3 +91,7 @@ Get-ComputerInfo,https://go.microsoft.com/fwlink/?LinkId=799466
Get-TimeZone,https://go.microsoft.com/fwlink/?LinkId=799468
Set-TimeZone,https://go.microsoft.com/fwlink/?LinkId=799469
Get-Uptime,https://go.microsoft.com/fwlink/?linkid=834862
ConvertFrom-Markdown,https://go.microsoft.com/fwlink/?linkid=2006503
Get-MarkdownOption,https://go.microsoft.com/fwlink/?linkid=2006371
Set-MarkdownOption,https://go.microsoft.com/fwlink/?linkid=2006265
Show-Markdown,https://go.microsoft.com/fwlink/?linkid=2006266
1 TopicTitle HelpURI
91 Get-TimeZone https://go.microsoft.com/fwlink/?LinkId=799468
92 Set-TimeZone https://go.microsoft.com/fwlink/?LinkId=799469
93 Get-Uptime https://go.microsoft.com/fwlink/?linkid=834862
94 ConvertFrom-Markdown https://go.microsoft.com/fwlink/?linkid=2006503
95 Get-MarkdownOption https://go.microsoft.com/fwlink/?linkid=2006371
96 Set-MarkdownOption https://go.microsoft.com/fwlink/?linkid=2006265
97 Show-Markdown https://go.microsoft.com/fwlink/?linkid=2006266