public void ProduceDefaultValues() { var parser = new MarkdownParser(); const string docFormatString = @" # Get-Foo ## PARAMETERS ### Name [String] = PowerShell ```powershell [Parameter(ParameterSetName = 'Set 1')] ``` "; var doc = parser.ParseString(docFormatString); MamlCommand mamlCommand = (new ModelTransformer()).NodeModelToMamlModel(doc).First(); Assert.Equal(mamlCommand.Name, "Get-Foo"); Assert.Equal(1, mamlCommand.Parameters.Count); var parameter = mamlCommand.Parameters[0]; Assert.Equal(parameter.DefaultValue, "PowerShell"); }
public void ProducesParameterForDefaultParameterName() { var parser = new MarkdownParser(); const string docFormatString = @" # Get-Foo ## PARAMETERS ### informationVariable ### force [switch] ```powershell [Parameter(Mandatory=$false)] ``` "; var doc = parser.ParseString(docFormatString); MamlCommand mamlCommand = (new ModelTransformer()).NodeModelToMamlModel(doc).First(); Assert.Equal(mamlCommand.Name, "Get-Foo"); Assert.Equal(2, mamlCommand.Parameters.Count); var fooParam = mamlCommand.Parameters[0]; Assert.Equal("informationVariable", fooParam.Name); Assert.Equal(null, fooParam.Type); }
public void ProducesParameterValueGroup() { var parser = new MarkdownParser(); const string docFormatString = @" # Get-Foo ## PARAMETERS ### foo [string] ```powershell [ValidateSet('a', 'b', 'c')] ``` "; var doc = parser.ParseString(docFormatString); MamlCommand mamlCommand = (new ModelTransformer()).NodeModelToMamlModel(doc).First(); Assert.Equal(mamlCommand.Name, "Get-Foo"); Assert.Equal(1, mamlCommand.Syntax.Count); Assert.Equal(1, mamlCommand.Syntax[0].Parameters.Count); var fooParam = mamlCommand.Syntax[0].Parameters[0]; Assert.Equal("foo", fooParam.Name); Assert.Equal("string", fooParam.Type); Assert.Equal(3, fooParam.ParameterValueGroup.Count); Assert.Equal("a", fooParam.ParameterValueGroup[0]); Assert.Equal("b", fooParam.ParameterValueGroup[1]); Assert.Equal("c", fooParam.ParameterValueGroup[2]); }
private void AddExamples(MamlCommand command) { AddHeader(ModelTransformerBase.COMMAND_ENTRIES_HEADING_LEVEL, MarkdownStrings.EXAMPLES); foreach (var example in command.Examples) { var extraNewLine = ShouldBreak(example.FormatOption); AddHeader(ModelTransformerBase.EXAMPLE_HEADING_LEVEL, GetExampleTitle(example.Title), extraNewLine: extraNewLine); if (!string.IsNullOrEmpty(example.Introduction)) { AddParagraphs(example.Introduction); } if (example.Code != null) { for (var i = 0; i < example.Code.Length; i++) { AddCodeSnippet(example.Code[i].Text, example.Code[i].LanguageMoniker); } } if (!string.IsNullOrEmpty(example.Remarks)) { AddParagraphs(example.Remarks); } } }
public void ProducesSyntaxInTheRightOrder() { const string docFormatString = @" # Get-Foo ## PARAMETERS ### SecondSetParam [String] ```powershell [Parameter(ParameterSetName = 'Set 2')] ``` ### FirstSetParam [String] ```powershell [Parameter(ParameterSetName = 'Set 1')] ``` "; var doc = ParseString(docFormatString); MamlCommand mamlCommand = NodeModelToMamlModelV1(doc).First(); Assert.Equal(mamlCommand.Name, "Get-Foo"); Assert.Equal(2, mamlCommand.Syntax.Count); var syntax1 = mamlCommand.Syntax[0]; var syntax2 = mamlCommand.Syntax[1]; Assert.Equal(syntax1.Parameters.Count, 1); Assert.Equal(syntax2.Parameters.Count, 1); Assert.Equal(syntax1.Parameters[0].Name, "FirstSetParam"); Assert.Equal(syntax2.Parameters[0].Name, "SecondSetParam"); }
public static string MamlModelToString(MamlCommand mamlCommand) { var serializer = new SerializerBuilder() .WithNamingConvention(new CamelCaseNamingConvention()) .Build(); var model = new YamlCommand { Name = mamlCommand.Name, Notes = mamlCommand.Notes, Remarks = mamlCommand.Description, Summary = mamlCommand.Synopsis, Examples = mamlCommand.Examples.Select(CreateExample).ToList(), Inputs = mamlCommand.Inputs.Select(CreateInputOutput).ToList(), Links = mamlCommand.Links.Select(CreateLink).ToList(), Module = new YamlModule { Name = mamlCommand.ModuleName }, OptionalParameters = mamlCommand.Parameters.Where(p => !p.Required).Select(CreateParameter).ToList(), Outputs = mamlCommand.Outputs.Select(CreateInputOutput).ToList(), RequiredParameters = mamlCommand.Parameters.Where(p => p.Required).Select(CreateParameter).ToList(), Syntaxes = mamlCommand.Syntax.Select(CreateSyntax).ToList() }; using (var writer = new StringWriter()) { serializer.Serialize(writer, model); writer.Flush(); return(writer.ToString()); } }
public void RendererNormalizeQuotesAndDashes() { var renderer = new MarkdownV2Renderer(ParserMode.Full); MamlCommand command = new MamlCommand() { Name = "Test-Quotes", Synopsis = new SectionBody("Example synopsis", SectionFormatOption.LineBreakAfterHeader), Description = new SectionBody(@"”“‘’––-") }; string markdown = renderer.MamlModelToString(command, null); Common.AssertMultilineEqual(@"--- schema: 2.0.0 --- # Test-Quotes ## SYNOPSIS Example synopsis ## DESCRIPTION """"''--- ## PARAMETERS ### CommonParameters This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). ", markdown); }
public void ProducesParameterValueGroup() { const string docFormatString = @" # Get-Foo ## PARAMETERS ### foo ```yaml Type: string Accepted values: a, b, c ``` "; var doc = ParseString(docFormatString); MamlCommand mamlCommand = NodeModelToMamlModelV2(doc).First(); Assert.Equal(mamlCommand.Name, "Get-Foo"); Assert.Equal(1, mamlCommand.Syntax.Count); Assert.Equal(1, mamlCommand.Syntax[0].Parameters.Count); var fooParam = mamlCommand.Syntax[0].Parameters[0]; Assert.Equal("foo", fooParam.Name); Assert.Equal("string", fooParam.Type); Assert.Equal(3, fooParam.ParameterValueGroup.Count); Assert.Equal("a", fooParam.ParameterValueGroup[0]); Assert.Equal("b", fooParam.ParameterValueGroup[1]); Assert.Equal("c", fooParam.ParameterValueGroup[2]); }
public void ProducesParameterForDefaultParameterName() { const string docFormatString = @" # Get-Foo ## PARAMETERS ### informationVariable ### force ```yaml Type: SwitchParameter Required: false ``` "; var doc = ParseString(docFormatString); MamlCommand mamlCommand = NodeModelToMamlModelV2(doc).First(); Assert.Equal(mamlCommand.Name, "Get-Foo"); Assert.Equal(2, mamlCommand.Parameters.Count); var informationVariable = mamlCommand.Parameters[0]; Assert.Equal("informationVariable", informationVariable.Name); Assert.Equal(null, informationVariable.Type); Assert.Equal(true, informationVariable.ValueRequired); var force = mamlCommand.Parameters[1]; Assert.Equal("force", force.Name); Assert.Equal("SwitchParameter", force.Type); Assert.Equal(false, force.ValueRequired); }
public void UsesEntryToMarkGlobbing() { const string docFormatString = @" # Get-Foo ## PARAMETERS ### Name ```yaml Type: string Accept wildcard characters: true ``` "; var doc = ParseString(docFormatString); MamlCommand mamlCommand = NodeModelToMamlModelV2(doc).First(); Assert.Equal(mamlCommand.Name, "Get-Foo"); Assert.Equal(1, mamlCommand.Parameters.Count); var parameter = mamlCommand.Parameters[0]; Assert.True(parameter.Globbing); Assert.Equal(parameter.Type, "string"); }
public void ProduceDefaultValues() { const string docFormatString = @" # Get-Foo ## PARAMETERS ### Name ```yaml Type: String Parameter Sets: Set1 Aliases: Required: False Position: Named Default value: PowerShell Accept pipeline input: False Accept wildcard characters: False ``` "; var doc = ParseString(docFormatString); MamlCommand mamlCommand = NodeModelToMamlModelV2(doc).First(); Assert.Equal(mamlCommand.Name, "Get-Foo"); Assert.Equal(1, mamlCommand.Parameters.Count); var parameter = mamlCommand.Parameters[0]; Assert.Equal(parameter.DefaultValue, "PowerShell"); }
public void PreserveFormattingIfNeeded() { const string description = @"Hello This description block test formatting preservance. -- It need to -- Be. Very. [Weiredly](formatted) \< to keep > the purpose. \\( \\\( \( This is intentional. * we * dont't want. * Mess up with user's formatting. "; const string docFormatString = @" # Get-Foo ## DESCRIPTION " + description; var doc = ParseStringPreserveFormat(docFormatString); MamlCommand mamlCommand = NodeModelToMamlModelV2(doc).First(); Assert.Equal("Get-Foo", mamlCommand.Name); Assert.Equal(description, mamlCommand.Description); }
private static XElement CreateCommandElement(MamlCommand command) { var commandParts = command.Name.Split('-'); var verb = commandParts[0]; var noun = command.Name.Substring(Math.Min(verb.Length + 1, command.Name.Length)); return(new XElement(commandNS + "command", new XAttribute(XNamespace.Xmlns + "maml", mamlNS), new XAttribute(XNamespace.Xmlns + "command", commandNS), new XAttribute(XNamespace.Xmlns + "dev", devNS), new XAttribute(XNamespace.Xmlns + "MSHelp", msHelpNS), new XElement(commandNS + "details", new XElement(commandNS + "name", command.Name), new XElement(commandNS + "verb", verb), new XElement(commandNS + "noun", noun), 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?.Text))), new XElement(commandNS + "examples", command.Examples.Select(example => CreateExample(example))), new XElement(commandNS + "relatedLinks", command.Links.Select(link => CreateLink(link))))); }
public void ReturnsSyntaxString() { var command = new MamlCommand() { Name = "Get-Foo", SupportCommonParameters = true }; var param1 = new MamlParameter() { Name = "Bar", Type = "BarObject" }; var syntax = new MamlSyntax() { IsDefault = true }; syntax.Parameters.Add(param1); string syntaxString = MarkdownV2Renderer.GetSyntaxString(command, syntax); Assert.Equal("Get-Foo [-Bar <BarObject>] [<CommonParameters>]", syntaxString); }
public void UsesSupportsWildCardsToMarkGlobbing() { var parser = new MarkdownParser(); const string docFormatString = @" # Get-Foo ## PARAMETERS ### Name [String] ``` [SupportsWildCards()] ``` "; var doc = parser.ParseString(docFormatString); MamlCommand mamlCommand = (new ModelTransformer()).NodeModelToMamlModel(doc).First(); Assert.Equal(mamlCommand.Name, "Get-Foo"); Assert.Equal(1, mamlCommand.Parameters.Count); var parameter = mamlCommand.Parameters[0]; Assert.True(parameter.Globbing); Assert.Equal(parameter.Type, "String"); }
private void GatherSyntax(MamlCommand command) { var parameterSetNames = GetParameterSetNames(); if (parameterSetNames.Count == 0) { // special case: there are no parameters and hence there is only one parameter set MamlSyntax syntax = new MamlSyntax(); command.Syntax.Add(syntax); } foreach (var setName in parameterSetNames) { MamlSyntax syntax = new MamlSyntax(); if (setName == ALL_PARAM_SETS_MONIKER) { if (parameterSetNames.Count == 1) { // special case: there is only one parameter set and it's the deafult one // we don't specify the name in this case. } else { continue; } } else { syntax.ParameterSetName = setName; } FillUpSyntax(syntax, setName); command.Syntax.Add(syntax); } }
private void AddLinks(int levelRoot, MamlCommand command) { if (command.Links != null && command.Links.Count > 0) { AddHeader(levelRoot, ModelTransformerBase.COMMAND_ENTRIES_HEADING_LEVEL, MarkdownStrings.RELATED_LINKS, extraNewLine: true); foreach (var link in command.Links) { if (link.IsSimplifiedTextLink) { _stringBuilder.AppendFormat("{0}", link.LinkName); } else { var name = link.LinkName; if (string.IsNullOrEmpty(name)) { // we need a valid name to produce a valid markdown name = link.LinkUri; } _stringBuilder.AppendFormat("[{0}]({1}){2}{2}", name, link.LinkUri, NewLine); } } } }
public MamlCommand Merge(Dictionary <string, MamlCommand> applicableTag2Model) { if (applicableTag2Model.Count == 0) { throw new ArgumentException("applicableTag2Model"); } var tagsModel = applicableTag2Model.ToList(); // just take one model to use name from it and such var referenceModel = applicableTag2Model.First().Value; MamlCommand result = null; result = new MamlCommand() { Name = referenceModel.Name, 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 }; result.Links.AddRange(MergeSimplifiedLinks(tagsModel.Select(pair => pair.Value.Links))); MergeExamples(result, applicableTag2Model); result.Inputs.AddRange(MergeEntityList(tagsModel.Select(pair => pair.Value.Inputs))); result.Outputs.AddRange(MergeEntityList(tagsModel.Select(pair => pair.Value.Outputs))); MergeParameters(result, applicableTag2Model); return(result); }
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); }
private void RelatedLinksRule(MamlCommand commmand) { var paragraphNode = ParagraphNodeRule(); if (paragraphNode == null) { return; } foreach (var paragraphSpan in paragraphNode.Spans) { var linkSpan = paragraphSpan as HyperlinkSpan; if (linkSpan != null) { commmand.Links.Add(new MamlLink() { LinkName = linkSpan.Text, LinkUri = linkSpan.Uri }); } else { throw new HelpSchemaException(paragraphSpan.SourceExtent, "Expect hyperlink, but got " + paragraphSpan.Text); } } }
public void RendererCreatesWorkflowParametersEntryWithoutDescriptions() { var renderer = new MarkdownV2Renderer(ParserMode.Full); MamlCommand command = new MamlCommand() { Name = "Workflow", IsWorkflow = true }; command.Syntax.Add(new MamlSyntax()); string markdown = renderer.MamlModelToString(command, null); Common.AssertMultilineEqual(@"--- schema: 2.0.0 --- # Workflow ## SYNTAX ``` Workflow [<WorkflowCommonParameters>] [<CommonParameters>] ``` ## PARAMETERS ### WorkflowCommonParameters This cmdlet supports the following workflow common parameters: -PSParameterCollection, -PSComputerName, -PSCredential, -PSConnectionRetryCount, -PSConnectionRetryIntervalSec, -PSRunningTimeoutSec, -PSElapsedTimeoutSec, -PSPersist, -PSAuthentication, -PSAuthenticationLevel, -PSApplicationName, -PSPort, -PSUseSSL, -PSConfigurationName, -PSConnectionURI, -PSAllowRedirection, -PSSessionOption, -PSCertificateThumbprint, -PSPrivateMetadata, -AsJob, -JobName, and -InputObject. For more information, see [about_WorkflowCommonParameters](http://go.microsoft.com/fwlink/p/?LinkID=533952). ### CommonParameters This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). ", markdown); }
private void AddLinks(MamlCommand command) { PushTag("command:relatedLinks"); foreach (MamlLink Link in command.Links) { if (Link.IsSimplifiedTextLink) { // that should never happen. // we don't know how to represent non-parsed links in maml. // skipping it. // TODO: error out? continue; } PushTag("maml:navigationLink"); PushTag("maml:linkText"); _stringBuilder.Append(XmlEscape(Link.LinkName)); PopTag(1); PushTag("maml:uri"); _stringBuilder.Append(XmlEscape(Link.LinkUri)); PopTag(1); PopTag(1); } PopTag(1); }
public void ProducesSyntaxForTwoSets() { const string docFormatString = @" # Get-Foo ## PARAMETERS ### TypeName [String] ```powershell [Parameter(Mandatory = $true, ParameterSetName = 'Set 1')] [Parameter(ParameterSetName = 'Set 2')] ``` "; var doc = ParseString(docFormatString); MamlCommand mamlCommand = NodeModelToMamlModelV1(doc).First(); Assert.Equal(mamlCommand.Name, "Get-Foo"); Assert.Equal(2, mamlCommand.Syntax.Count); var syntax1 = mamlCommand.Syntax[0]; var syntax2 = mamlCommand.Syntax[1]; Assert.Equal(syntax1.Parameters.Count, 1); Assert.Equal(syntax2.Parameters.Count, 1); Assert.Equal(syntax1.Parameters[0].Name, "TypeName"); Assert.Equal(syntax2.Parameters[0].Name, "TypeName"); Assert.Equal(syntax1.Parameters[0].Type, "String"); Assert.Equal(syntax2.Parameters[0].Type, "String"); Assert.Equal(syntax1.Parameters[0].Required, false); Assert.Equal(syntax2.Parameters[0].Required, true); }
public void RendererProduceNameAndSynopsis() { MamlRenderer renderer = new MamlRenderer(); MamlCommand command = new MamlCommand() { Name = "Get-Foo", Synopsis = "This is the synopsis", Description = "This is a long description." }; command.Parameters.Add(new MamlParameter() { Type = "String", Name = "Name", Required = true, Description = "Parameter Description.", VariableLength = true, Globbing = true, PipelineInput = "True (ByValue)", Position = "1", Aliases = new string [] { "GF", "Foos", "Do" }, } ); command.Inputs.Add(new MamlInputOutput() { TypeName = "String", Description = "Input Description goes here!" } ); command.Outputs.Add(new MamlInputOutput() { TypeName = "String", Description = "Output Description goes here!" } ); command.Examples.Add(new MamlExample() { Title = "Example 1", Code = "PS:> Get-Help -YouNeedIt", Remarks = "This does stuff!" } ); command.Links.Add(new MamlLink() { LinkName = "PowerShell made by Microsoft Hackathon", LinkUri = "www.microsoft.com" } ); string maml = renderer.MamlModelToString(new [] { command }); string[] name = EndToEndTests.GetXmlContent(maml, "/helpItems/command:command/command:details/command:name"); Assert.Equal(1, name.Length); Assert.Equal("Get-Foo", name[0]); string[] synopsis = EndToEndTests.GetXmlContent(maml, "/helpItems/command:command/command:details/maml:description/maml:para"); Assert.Equal(1, synopsis.Length); Assert.Equal("This is the synopsis", synopsis[0]); }
protected void ParametersRule(MamlCommand command) { while (ParameterRule(command)) { } GatherSyntax(command); }
private void AddInputs(MamlCommand command) { AddHeader(ModelTransformerBase.COMMAND_ENTRIES_HEADING_LEVEL, MarkdownStrings.INPUTS); foreach (var io in command.Inputs) { AddInputOutput(io); } }
private void AddNotes(MamlCommand command) { PushTag("maml:alertSet"); PushTag("maml:alert"); AddParas(command.Notes); PopTag("maml:alert"); PopTag("maml:alertSet"); }
private void ParametersRule(MamlCommand commmand) { while (ParameterRule(commmand)) { } this.GatherParameterDetails(commmand); }
public void RenderesWithPreservedFormatting() { var renderer = new MarkdownV2Renderer(ParserMode.FormattingPreserve); MamlCommand command = new MamlCommand() { Name = "Get-Foo", SupportCommonParameters = false, Description = new SectionBody(@"Hello This \<description \> should be preserved by renderer With all [hyper](https://links.com) and yada -- yada * Also * This list. May look. A little weired * [ ] But * [ ] It should be left" ) }; command.Links.Add( new MamlLink(isSimplifiedTextLink: true) { LinkName = "Any text [can](go here)\r\n[any](text)" } ); string markdown = renderer.MamlModelToString(command, null); Common.AssertMultilineEqual(@"--- schema: 2.0.0 --- # Get-Foo ## SYNOPSIS ## SYNTAX ## DESCRIPTION " + command.Description + @" ## EXAMPLES ## PARAMETERS ## INPUTS ## OUTPUTS ## NOTES ## RELATED LINKS Any text [can](go here) [any](text)", markdown); }
protected void ExamplesRule(MamlCommand commmand) { MamlExample example; while ((example = ExampleRule()) != null) { commmand.Examples.Add(example); } }
public IEnumerable<MamlCommand> NodeModelToMamlModel(DocumentNode node) { _root = node; if (_root.Children == null) { // HACK: _rootEnumerator = (new LinkedList<MarkdownNode>()).GetEnumerator(); } else { _rootEnumerator = _root.Children.GetEnumerator(); } List<MamlCommand> commands = new List<MamlCommand>(); MarkdownNode markdownNode; while ((markdownNode = GetNextNode()) != null) { if (markdownNode is HeadingNode) { var headingNode = markdownNode as HeadingNode; switch (headingNode.HeadingLevel) { case COMMAND_NAME_HEADING_LEVEL: { MamlCommand command = new MamlCommand() { Name = headingNode.Text, Extent = headingNode.SourceExtent }; if (_infoCallback != null) { Console.WriteLine("Start processing command " + command.Name); } // fill up command while (SectionDispatch(command)) { } commands.Add(command); break; } default: throw new HelpSchemaException(headingNode.SourceExtent, "Booo, I don't know what is the heading level " + headingNode.HeadingLevel); } } } return commands; }
public void RendererProduceSyntaxAndParameter() { MamlRenderer renderer = new MamlRenderer(); MamlCommand command = new MamlCommand() { Name = "Get-Foo", }; var param1 = new MamlParameter() { Type = "String", Name = "Param1", Position = "Named" }; var param2 = new MamlParameter() { Type = "System.Int32", Name = "Param2", Position = "Named" }; command.Parameters.Add(param1); command.Parameters.Add(param2); var syntax = new MamlSyntax(); syntax.Parameters.Add(param1); syntax.Parameters.Add(param2); command.Syntax.Add(syntax); string maml = renderer.MamlModelToString(new[] { command }); string[] syntaxItemName = EndToEndTests.GetXmlContent(maml, "/helpItems/command:command/command:syntax/command:syntaxItem/maml:name"); Assert.Equal(1, syntaxItemName.Length); Assert.Equal("Get-Foo", syntaxItemName[0]); string[] nameSyntax = EndToEndTests.GetXmlContent(maml, "/helpItems/command:command/command:syntax/command:syntaxItem/command:parameter/maml:name"); Assert.Equal(2, nameSyntax.Length); Assert.Equal("Param1", nameSyntax[0]); Assert.Equal("Param2", nameSyntax[1]); string[] nameParam = EndToEndTests.GetXmlContent(maml, "/helpItems/command:command/command:parameters/command:parameter/maml:name"); Assert.Equal(2, nameParam.Length); Assert.Equal("Param1", nameParam[0]); Assert.Equal("Param2", nameParam[1]); }
private void AddParameter(MamlCommand command, MamlParameter parameter, bool inSyntax) { var attributes = "required=\"" + parameter.Required.ToString().ToLower() + "\" " + "variableLength=\"" + parameter.VariableLength.ToString().ToLower() + "\" " + "globbing=\"" + parameter.Globbing.ToString().ToLower() + "\" " + "pipelineInput=\"" + parameter.PipelineInput + "\" " + "position=\"" + parameter.Position.ToLower() + "\" " + "aliases=\""; attributes += parameter.Aliases.Length > 0 ? string.Join(", ", parameter.Aliases) : "none"; attributes += "\""; PushTag("command:parameter", attributes); PushTag("maml:name"); _stringBuilder.Append(XmlEscape(parameter.Name)); PopTag("maml:name"); PushTag("maml:Description"); AddParas(parameter.Description); PopTag("maml:Description"); if (inSyntax && parameter.ParameterValueGroup.Count > 0) { AddParameterValueGroup(parameter.ParameterValueGroup); } attributes = "required=\"" + parameter.ValueRequired.ToString().ToLower() + "\" " + "variableLength=\"" + parameter.ValueVariableLength.ToString().ToLower(); attributes += "\""; string mamlType = ConvertPSTypeToMamlType(parameter.Type); // this is weired quirk inside <syntax>: // we don't add [switch] info to make it appear good. if (!inSyntax || mamlType != "SwitchParameter") { PushTag("command:parameterValue", attributes); _stringBuilder.Append(XmlEscape(mamlType)); PopTag("command:parameterValue"); } PushTag("dev:type"); PushTag("maml:name"); _stringBuilder.Append(XmlEscape(mamlType)); PopTag("maml:name"); _stringBuilder.Append("<maml:uri />"); PopTag("dev:type"); // Region defaultValue PushTag("dev:defaultValue"); if (mamlType == "SwitchParameter" && parameter.DefaultValue == null) { _stringBuilder.Append("False"); } else { if (parameter.DefaultValue != null) { _stringBuilder.Append(XmlEscape(parameter.DefaultValue)); } else { // sometimes default is none, but empty makes more sense. // _stringBuilder.Append("none"); } } PopTag("dev:defaultValue"); // closing tag PopTag("command:parameter"); }
/// <summary> /// /// </summary> /// <param name="command"></param> /// <returns>true if Section was found</returns> private bool SectionDispatch(MamlCommand command) { var node = GetNextNode(); var headingNode = GetHeadingWithExpectedLevel(node, COMMAND_ENTRIES_HEADING_LEVEL); if (headingNode == null) { return false; } switch (headingNode.Text.ToUpper()) { case "DESCRIPTION": { command.Description = SimpleTextSectionRule(); break; } case "SYNOPSIS": { command.Synopsis = SimpleTextSectionRule(); break; } case "PARAMETERS": { ParametersRule(command); break; } case "INPUTS": { InputsRule(command); break; } case "OUTPUTS": { OutputsRule(command); break; } case "NOTES": { command.Notes = SimpleTextSectionRule(); break; } case "EXAMPLES": { ExamplesRule(command); break; } case "RELATED LINKS": { RelatedLinksRule(command); break; } default: { throw new HelpSchemaException(headingNode.SourceExtent, "Unexpected header name " + headingNode.Text); } } return true; }
public void RendererProduceNameAndSynopsis() { MamlRenderer renderer = new MamlRenderer(); MamlCommand command = new MamlCommand() { Name = "Get-Foo", Synopsis = "This is the synopsis", Description = "This is a long description." }; command.Parameters.Add(new MamlParameter() { Type = "String", Name = "Name", Required = true, Description = "Parameter Description.", VariableLength = true, Globbing = true, PipelineInput = "True (ByValue)", Position = "1", Aliases = new string []{"GF","Foos","Do"}, } ); command.Inputs.Add(new MamlInputOutput() { TypeName = "String", Description = "Input Description goes here!" } ); command.Outputs.Add(new MamlInputOutput() { TypeName = "String", Description = "Output Description goes here!" } ); command.Examples.Add(new MamlExample() { Title = "Example 1", Code = "PS:> Get-Help -YouNeedIt", Remarks = "This does stuff!" } ); command.Links.Add(new MamlLink() { LinkName = "PowerShell made by Microsoft Hackathon", LinkUri = "www.microsoft.com" } ); string maml = renderer.MamlModelToString(new [] {command}); string[] name = EndToEndTests.GetXmlContent(maml, "/helpItems/command:command/command:details/command:name"); Assert.Equal(1, name.Length); Assert.Equal("Get-Foo", name[0]); string[] synopsis = EndToEndTests.GetXmlContent(maml, "/helpItems/command:command/command:details/maml:description/maml:para"); Assert.Equal(1, synopsis.Length); Assert.Equal("This is the synopsis", synopsis[0]); }
private void AddExamples(MamlCommand command) { PushTag("command:examples"); foreach (MamlExample example in command.Examples) { PushTag("command:example"); PushTag("maml:title"); _stringBuilder.Append(XmlEscape(example.Title)); PopTag("maml:title"); PushTag("dev:code"); _stringBuilder.Append(XmlEscape(example.Code)); PopTag("dev:code"); PushTag("dev:remarks"); AddParas(example.Remarks); PopTag("dev:remarks"); PopTag("command:example"); } PopTag("command:examples"); }
private void AddSyntax(MamlCommand command) { PushTag("command:syntax"); foreach (MamlSyntax syntaxItem in command.Syntax) { PushTag("command:syntaxItem"); _stringBuilder.AppendFormat("<maml:name>{0}</maml:name>{1}", XmlEscape(command.Name), Environment.NewLine); foreach (MamlParameter parameter in syntaxItem.Parameters) { AddParameter(command, parameter, inSyntax: true); } PopTag("command:syntaxItem"); } PopTag("command:syntax"); }
private void AddParameters(MamlCommand command) { PushTag("command:parameters"); foreach (MamlParameter parameter in command.Parameters) { AddParameter(command, parameter, inSyntax:false); } PopTag("command:parameters"); }
private void AddOutputs(MamlCommand command) { PushTag("command:returnValues"); foreach (var output in command.Outputs) { PushTag("command:returnValue"); PushTag("dev:type"); PushTag("maml:name"); _stringBuilder.Append(XmlEscape(output.TypeName)); PopTag("maml:name"); PopTag("dev:type"); PushTag("maml:description"); AddParas(output.Description); PopTag("maml:description"); PopTag("command:returnValue"); } PopTag("command:returnValues"); }
private void InputsRule(MamlCommand commmand) { MamlInputOutput input; while ((input = InputOutputRule()) != null) { commmand.Inputs.Add(input); } }
private void OutputsRule(MamlCommand commmand) { MamlInputOutput output; while ((output = InputOutputRule()) != null) { commmand.Outputs.Add(output); } }
private void ExamplesRule(MamlCommand commmand) { MamlExample example; while ((example = ExampleRule()) != null) { commmand.Examples.Add(example); } }
private void AddInputs(MamlCommand command) { PushTag("command:inputTypes"); foreach (var input in command.Inputs) { PushTag("command:inputType"); PushTag("dev:type"); PushTag("maml:name"); _stringBuilder.Append(XmlEscape(input.TypeName)); PopTag("maml:name"); PopTag("dev:type"); PushTag("maml:description"); AddParas(input.Description); PopTag("maml:description"); PopTag("command:inputType"); } PopTag("command:inputTypes"); }
private void AddDescription(MamlCommand command) { PushTag("maml:description"); AddParas(command.Description); PopTag(1); }
private void AddSynopsis(MamlCommand command) { PushTag("maml:description"); AddParas(command.Synopsis); PopTag(1); }
private void AddLinks(MamlCommand command) { PushTag("command:relatedLinks"); foreach (MamlLink Link in command.Links) { PushTag("maml:navigationLink"); PushTag("maml:linkText"); _stringBuilder.Append(XmlEscape(Link.LinkName)); PopTag(1); PushTag("maml:uri"); _stringBuilder.Append(XmlEscape(Link.LinkUri)); PopTag(1); PopTag(1); } PopTag(1); }
public void RendererProduceEscapeXmlSpecialChars() { MamlRenderer renderer = new MamlRenderer(); MamlCommand command = new MamlCommand() { Name = "Get-Foo", Synopsis = "<port&number>" // < and > should be properly escaped }; string maml = renderer.MamlModelToString(new[] { command }); string[] synopsis = EndToEndTests.GetXmlContent(maml, "/helpItems/command:command/command:details/maml:description/maml:para"); Assert.Equal(1, synopsis.Length); Assert.Equal(synopsis[0], command.Synopsis); }
/// <summary> /// /// </summary> /// <param name="command"></param> /// <returns>true if Parameter was found</returns> private bool ParameterRule(MamlCommand command) { // grammar: // #### Name [TypeName] - mandatory // ```powershell - optional // [Parameter(...)] // ``` // Description - optional var node = GetNextNode(); var headingNode = GetHeadingWithExpectedLevel(node, PARAMETER_NAME_HEADING_LEVEL); if (headingNode == null) { return false; } var name = headingNode.Text.Split()[0]; MamlParameter parameter = new MamlParameter() { Name = name, Extent = headingNode.SourceExtent }; int equalIndex = headingNode.Text.IndexOf('='); string headingNodeText; if (equalIndex >= 0) { parameter.DefaultValue = headingNode.Text.Substring(equalIndex + 1).Trim(); // trim it for this case from PSReadLine: // #### WordDelimiters [Int32] = ;:,.[]{}()/\|^&*-=+ // We need to make sure that closing ] corresponds to [Int32], so it's the last ] before first = sign. headingNodeText = headingNode.Text.Substring(0, equalIndex); } else { headingNodeText = headingNode.Text; } int typeBeginIndex = headingNodeText.IndexOf('['); int typeEndIndex = headingNodeText.LastIndexOf(']'); if (typeBeginIndex >= 0 && typeEndIndex > 0) { parameter.Type = headingNodeText.Substring(typeBeginIndex + 1, typeEndIndex - typeBeginIndex - 1); } node = GetNextNode(); ParagraphNode descriptionNode = null; CodeBlockNode attributesNode = null; // it can be the end if (node != null) { switch (node.NodeType) { case MarkdownNodeType.Unknown: break; case MarkdownNodeType.Document: break; case MarkdownNodeType.Paragraph: descriptionNode = node as ParagraphNode; break; case MarkdownNodeType.Heading: // next parameter started UngetNode(node); break; case MarkdownNodeType.CodeBlock: attributesNode = node as CodeBlockNode; break; default: throw new ArgumentOutOfRangeException(); } if (descriptionNode == null) { descriptionNode = ParagraphNodeRule(); } } parameter.Description = GetTextFromParagraphNode(descriptionNode); parameter.AttributesText = attributesNode != null ? attributesNode.Text : string.Empty; if (parameter.AttributesText.Contains(@"[SupportsWildCards()]")) { parameter.Globbing = true; } command.Parameters.Add(parameter); return true; }
private void GatherParameterDetails(MamlCommand command) { const string parameterFormatString = @" {0} ${1}"; const string docFunctionFormatString = @" function Get-AttributeDocFunction {{ param( {0} ) }} $h = Get-Help Get-AttributeDocFunction $h.parameters.parameter "; // Create the Runspace on demand if (this.runspace == null) { this.runspace = RunspaceFactory.CreateRunspace(); this.runspace.Open(); } using (PowerShell powerShell = PowerShell.Create()) { var parameterBlocks = command .Parameters .Select(p => string.Format(parameterFormatString, p.AttributesText, ShiftName(p.Name))); var functionScript = string.Format( docFunctionFormatString, string.Join(",\r\n", parameterBlocks)); // TODO: There could be some security concerns with executing arbitrary // text here, need to investigate safer ways to do it. JEA? powerShell.Runspace = this.runspace; powerShell.AddScript(functionScript); var parameterDetailses = powerShell.Invoke<PSObject>(); if (powerShell.Streams.Error.Any()) { throw new HelpSchemaException(command.Extent, "Errors when processing command " + command.Name + ":\n" + string.Join(";\n", powerShell.Streams.Error)); } foreach (PSObject parameterDetailsPsObject in parameterDetailses) { var parameter = command.Parameters.FirstOrDefault( p => string.Equals(p.Name, UndoShiftName((string)parameterDetailsPsObject.Properties["name"].Value))); FillUpParameterFromPSObject(parameter, parameterDetailsPsObject); } powerShell.Commands.Clear(); powerShell.Commands.AddScript("$h.Syntax.syntaxItem"); var syntaxDetailses = powerShell.Invoke<PSObject>(); if (powerShell.Streams.Error.Any()) { throw new HelpSchemaException(command.Extent, "Errors when processing command " + command.Name + ":\n" + string.Join(";\n", powerShell.Streams.Error)); } var sortedSyntaxItems = syntaxDetailses.ToList(); sortedSyntaxItems.Sort((si1, si2) => String.CompareOrdinal(GetParameterSetNameFromSyntaxItem(si1), GetParameterSetNameFromSyntaxItem(si2))); foreach (var syntaxDetails in sortedSyntaxItems) { MamlSyntax syntax = new MamlSyntax(); var syntaxParams = (object[])syntaxDetails.Properties["parameter"].Value; foreach (PSObject syntaxParamPsObject in syntaxParams.OfType<PSObject>()) { string paramName = UndoShiftName((string) syntaxParamPsObject.Properties["name"].Value); MamlParameter parametersParameter = command.Parameters.FirstOrDefault(p => string.Equals(p.Name, paramName)); if (parametersParameter == null) { throw new HelpSchemaException(command.Extent, "Cannot find corresponding parameter for syntax item " + paramName); } MamlParameter syntaxParameter = new MamlParameter() { Name = parametersParameter.Name, Type = parametersParameter.Type }; FillUpParameterFromPSObject(syntaxParameter, syntaxParamPsObject); syntax.Parameters.Add(syntaxParameter); } command.Syntax.Add(syntax); } } }