diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ConvertFromMarkdownCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ConvertFromMarkdownCommand.cs index 4ae70ac4fd9..b80c48a6559 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ConvertFromMarkdownCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ConvertFromMarkdownCommand.cs @@ -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 @@ public class ConvertFromMarkdownCommand : PSCmdlet /// Gets or sets path to the file to convert from Markdown to MarkdownInfo. /// [ValidateNotNullOrEmpty] - [Parameter(ParameterSetName = PathParameterSet, Mandatory = true)] + [Parameter(ParameterSetName = PathParameterSet, Mandatory = true, Position = 0)] public string[] Path { get; set; } /// /// Gets or sets the path to the file to convert from Markdown to MarkdownInfo. /// [ValidateNotNullOrEmpty] + [Alias("PSPath", "LP")] [Parameter(ParameterSetName = LiteralPathParameterSet, Mandatory = true)] public string[] LiteralPath { get; set; } @@ -56,20 +57,29 @@ public class ConvertFromMarkdownCommand : PSCmdlet private const string LiteralPathParameterSet = "LiteralParamSet"; private const string InputObjParamSet = "InputObjParamSet"; private MarkdownConversionType conversionType = MarkdownConversionType.HTML; - private MarkdownOptionInfo mdOption = null; + private PSMarkdownOptionInfo mdOption = null; /// - /// Read the MarkdownOptionInfo set in SessionState. + /// Read the PSMarkdownOptionInfo set in SessionState. /// 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 @@ protected override void ProcessRecord() } } - private void ConvertEachFile(IEnumerable paths, MarkdownConversionType conversionType, bool isLiteral, MarkdownOptionInfo optionInfo) + private void ConvertEachFile(IEnumerable paths, MarkdownConversionType conversionType, bool isLiteral, PSMarkdownOptionInfo optionInfo) { foreach (var path in paths) { diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/MarkdownOptionCommands.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/MarkdownOptionCommands.cs index 88c6cd8e662..1109cd88461 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/MarkdownOptionCommands.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/MarkdownOptionCommands.cs @@ -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 { /// @@ -117,13 +117,13 @@ public class SetMarkdownOptionCommand : PSCmdlet /// Gets or sets InputObject. /// [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 @@ public class SetMarkdownOptionCommand : PSCmdlet /// 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 @@ protected override void EndProcessing() case InputObjectParamSet: object baseObj = InputObject.BaseObject; - mdOptionInfo = baseObj as MarkdownOptionInfo; + mdOptionInfo = baseObj as PSMarkdownOptionInfo; if (mdOptionInfo == null) { @@ -167,13 +167,12 @@ protected override void EndProcessing() 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 @@ protected override void EndProcessing() } } - private void SetOptions(MarkdownOptionInfo mdOptionInfo) + private void SetOptions(PSMarkdownOptionInfo mdOptionInfo) { if (!string.IsNullOrEmpty(Header1Color)) { @@ -245,18 +244,18 @@ private void SetOptions(MarkdownOptionInfo mdOptionInfo) /// [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"; /// /// Override EndProcessing. /// protected override void EndProcessing() { - WriteObject(SessionState.PSVariable.GetValue(MarkdownOptionInfoVariableName, new MarkdownOptionInfo())); + WriteObject(this.CommandInfo.Module.SessionState.PSVariable.GetValue(MarkdownOptionInfoVariableName, new PSMarkdownOptionInfo())); } } } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowMarkdownCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowMarkdownCommand.cs index 53b8338cb98..024e41d0620 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowMarkdownCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ShowMarkdownCommand.cs @@ -20,7 +20,7 @@ namespace Microsoft.PowerShell.Commands /// [Cmdlet( VerbsCommon.Show, "Markdown", - HelpUri = "TBD")] + HelpUri = "https://go.microsoft.com/fwlink/?linkid=2006266")] [OutputType(typeof(string))] public class ShowMarkdownCommand : PSCmdlet { diff --git a/src/Microsoft.PowerShell.MarkdownRender/MarkdownConverter.cs b/src/Microsoft.PowerShell.MarkdownRender/MarkdownConverter.cs index fae600d23b2..99becde6d10 100644 --- a/src/Microsoft.PowerShell.MarkdownRender/MarkdownConverter.cs +++ b/src/Microsoft.PowerShell.MarkdownRender/MarkdownConverter.cs @@ -59,7 +59,7 @@ public sealed class MarkdownConverter /// Specifies type of conversion, either VT100 or HTML. /// Specifies the rendering options for VT100 rendering. /// MarkdownInfo object with the converted output. - 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(); diff --git a/src/Microsoft.PowerShell.MarkdownRender/Microsoft.PowerShell.MarkdownRender.csproj b/src/Microsoft.PowerShell.MarkdownRender/Microsoft.PowerShell.MarkdownRender.csproj index 723dee057ac..a984c3f6610 100644 --- a/src/Microsoft.PowerShell.MarkdownRender/Microsoft.PowerShell.MarkdownRender.csproj +++ b/src/Microsoft.PowerShell.MarkdownRender/Microsoft.PowerShell.MarkdownRender.csproj @@ -8,6 +8,7 @@ + diff --git a/src/Microsoft.PowerShell.MarkdownRender/VT100EscapeSequences.cs b/src/Microsoft.PowerShell.MarkdownRender/VT100EscapeSequences.cs index 0e18d48347f..d3ffcb73378 100644 --- a/src/Microsoft.PowerShell.MarkdownRender/VT100EscapeSequences.cs +++ b/src/Microsoft.PowerShell.MarkdownRender/VT100EscapeSequences.cs @@ -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 @@ namespace Microsoft.PowerShell.MarkdownRender { /// - /// Enum to name all the properties of MarkdownOptionInfo. + /// Enum to name all the properties of PSMarkdownOptionInfo. /// public enum MarkdownOptionInfoProperty { @@ -73,7 +74,7 @@ public enum MarkdownOptionInfoProperty /// /// Class to represent color preference options for various Markdown elements. /// - public sealed class MarkdownOptionInfo + public sealed class PSMarkdownOptionInfo { private const char Esc = (char)0x1b; private const string EndSequence = "[0m"; @@ -133,9 +134,14 @@ public sealed class MarkdownOptionInfo /// public string EmphasisItalics { get; set; } + /// + /// Gets or sets a value indicating whether VT100 escape sequences should be added. Default it true. + /// + public bool EnableVT100Encoding { get; set; } + /// /// Get the property as an rendered escape sequence. - /// This is used for typesps1xml for displaying. + /// This is used by formatting system for displaying. /// /// Name of the property to get as escape sequence. /// Specified property name as escape sequence. @@ -184,11 +190,12 @@ public string AsEscapeSequence(MarkdownOptionInfoProperty propertyName) } /// - /// Initializes a new instance of class and sets dark as the default theme. + /// Initializes a new instance of the class and sets dark as the default theme. /// - public MarkdownOptionInfo() + public PSMarkdownOptionInfo() { SetDarkTheme(); + EnableVT100Encoding = true; } private const string Header1Dark = "[7m"; @@ -198,6 +205,7 @@ public MarkdownOptionInfo() 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 @@ public void SetDarkTheme() Header4 = Header4Dark; Header5 = Header5Dark; Header6 = Header6Dark; - Code = CodeDark; Link = LinkDark; Image = ImageDark; EmphasisBold = EmphasisBoldDark; EmphasisItalics = EmphasisItalicsDark; + SetCodeColor(isDarkTheme: true); } /// @@ -244,11 +252,17 @@ public void SetLightTheme() 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 @@ public class VT100EscapeSequences // For code blocks, [500@ make sure that the whole line has background color. private const string LongBackgroundCodeBlock = "[500@"; - private MarkdownOptionInfo options; + private PSMarkdownOptionInfo options; /// /// Initializes a new instance of the class. /// - /// MarkdownOptionInfo object to initialize with. - public VT100EscapeSequences(MarkdownOptionInfo optionInfo) + /// PSMarkdownOptionInfo object to initialize with. + public VT100EscapeSequences(PSMarkdownOptionInfo optionInfo) { if (optionInfo == null) { @@ -285,7 +299,7 @@ public VT100EscapeSequences(MarkdownOptionInfo optionInfo) /// Formatted Header 1 string. public string FormatHeader1(string headerText) { - return string.Concat(Esc, options.Header1, headerText, endSequence); + return FormatHeader(headerText, options.Header1); } /// @@ -295,7 +309,7 @@ public string FormatHeader1(string headerText) /// Formatted Header 2 string. public string FormatHeader2(string headerText) { - return string.Concat(Esc, options.Header2, headerText, endSequence); + return FormatHeader(headerText, options.Header2); } /// @@ -305,7 +319,7 @@ public string FormatHeader2(string headerText) /// Formatted Header 3 string. public string FormatHeader3(string headerText) { - return string.Concat(Esc, options.Header3, headerText, endSequence); + return FormatHeader(headerText, options.Header3); } /// @@ -315,7 +329,7 @@ public string FormatHeader3(string headerText) /// Formatted Header 4 string. public string FormatHeader4(string headerText) { - return string.Concat(Esc, options.Header4, headerText, endSequence); + return FormatHeader(headerText, options.Header4); } /// @@ -325,7 +339,7 @@ public string FormatHeader4(string headerText) /// Formatted Header 5 string. public string FormatHeader5(string headerText) { - return string.Concat(Esc, options.Header5, headerText, endSequence); + return FormatHeader(headerText, options.Header5); } /// @@ -335,7 +349,7 @@ public string FormatHeader5(string headerText) /// Formatted Header 6 string. public string FormatHeader6(string headerText) { - return string.Concat(Esc, options.Header6, headerText, endSequence); + return FormatHeader(headerText, options.Header6); } /// @@ -346,13 +360,29 @@ public string FormatHeader6(string headerText) /// Formatted code block string. 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 @@ public string FormatCode(string codeText, bool isInline) /// Formatted link string. 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 @@ public string FormatLink(string linkText, string url, bool hideUrl = true) 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; + } } /// @@ -401,7 +455,26 @@ public string FormatImage(string altText) 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; + } } } } diff --git a/src/Microsoft.PowerShell.MarkdownRender/VT100Renderer.cs b/src/Microsoft.PowerShell.MarkdownRender/VT100Renderer.cs index 59b8234d9ca..7049cc31246 100644 --- a/src/Microsoft.PowerShell.MarkdownRender/VT100Renderer.cs +++ b/src/Microsoft.PowerShell.MarkdownRender/VT100Renderer.cs @@ -18,8 +18,8 @@ public sealed class VT100Renderer : TextRendererBase /// Initializes a new instance of the class. /// /// TextWriter to write to. - /// MarkdownOptionInfo object with options. - public VT100Renderer(TextWriter writer, MarkdownOptionInfo optionInfo) : base(writer) + /// PSMarkdownOptionInfo object with options. + public VT100Renderer(TextWriter writer, PSMarkdownOptionInfo optionInfo) : base(writer) { EscapeSequences = new VT100EscapeSequences(optionInfo); diff --git a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs index b1ad7815a83..12df579f3c0 100644 --- a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs +++ b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/PowerShellCore_format_ps1xml.cs @@ -250,6 +250,10 @@ internal static IEnumerable GetFormatData() 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 ViewsOf_System_RuntimeType() @@ -1365,5 +1369,25 @@ private static IEnumerable ViewsOf_Microsoft_PowerShell_Co .EndRowDefinition() .EndTable()); } + + private static IEnumerable 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()); + } } } diff --git a/src/System.Management.Automation/engine/TypesV3_Ps1Xml.cs b/src/System.Management.Automation/engine/TypesV3_Ps1Xml.cs index 46c152f83bb..e12ad850a53 100644 --- a/src/System.Management.Automation/engine/TypesV3_Ps1Xml.cs +++ b/src/System.Management.Automation/engine/TypesV3_Ps1Xml.cs @@ -114,31 +114,6 @@ public static IEnumerable Get() 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; } } } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/MarkdownCmdlets.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/MarkdownCmdlets.Tests.ps1 index ac568ba6aad..246909b0deb 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/MarkdownCmdlets.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/MarkdownCmdlets.Tests.ps1 @@ -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" } - - "Code" { ($CodeFormatString -f "$esc[48;2;155;155;155;38;2;30;30;30m$CodeText$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" { + 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 : to vt100 using pipeline input - VT100 : ' -TestCases $TestCases { + param($element, $inputMD, $text, $codeFormatString, $codeText, $VT100) - It 'Can convert 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 diff --git a/test/powershell/engine/Help/assets/HelpURI/V3Cmdlets.csv b/test/powershell/engine/Help/assets/HelpURI/V3Cmdlets.csv index d5fccebd2d9..35deed27b37 100644 --- a/test/powershell/engine/Help/assets/HelpURI/V3Cmdlets.csv +++ b/test/powershell/engine/Help/assets/HelpURI/V3Cmdlets.csv @@ -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