private void WriteDetails(CmdletPageWriter writer, string typeDocumentation, string synopsis, Attribute awsCmdletAttribute) { if (!string.IsNullOrEmpty(synopsis)) { writer.AddPageElement(CmdletPageWriter.SynopsisElementKey, synopsis); } var doc = new StringBuilder(); if (!string.IsNullOrEmpty(typeDocumentation)) { doc.Append(typeDocumentation); } var legacyAlias = ExtractLegacyAlias(awsCmdletAttribute); if (!string.IsNullOrEmpty(legacyAlias)) { doc.AppendLine("<br/>"); doc.AppendLine("<br/>"); doc.AppendFormat("Note: For scripts written against earlier versions of this module this cmdlet can also be invoked with the alias, <i>{0}</i>.", legacyAlias); } if (doc.Length > 0) { writer.AddPageElement(CmdletPageWriter.DescriptionElementKey, doc.ToString()); } }
private void WriteParameters(CmdletPageWriter writer, string cmdletName, IEnumerable <SimplePropertyInfo> allProperties, bool commonParameters) { var pageElementKey = commonParameters ? CmdletPageWriter.CommonParametersElementKey : CmdletPageWriter.ParametersElementKey; var sb = new StringBuilder(); // Microsoft cmdlets list the parameters in alpha order here, so do the same (leaving metadata/paging // params in the correct order) foreach (var property in allProperties.Where(p => CommonParameters.Contains(p.Name) ^ !commonParameters).OrderBy(p => p.Name)) { sb.Append("<div class=\"parameter\">"); var typeName = GetTypeDisplayName(property.PropertyType, true); var inputTypeDocLink = PredictHtmlDocsLink(typeName); if (!string.IsNullOrEmpty(inputTypeDocLink)) { if (_msdnDocLinks.ContainsKey(typeName)) { // Open the MSDN links with _blank to open in a new tab sb.Append($"<div class=\"parameterName\">-{property.Name} <<a href=\"{inputTypeDocLink}\"{(RequiresLinkTarget(typeName) ? " target=\"blank\" rel=\"noopener noreferrer\"" : "")}>{GetTypeDisplayName(property.PropertyType, false)}</a>></div>"); } else { // For links to elsewhere in PowerShell or the SDK, open in the same tab via _parent to preserve the referrer for analytics sb.Append($"<div class=\"parameterName\">-{property.Name} <<a href=\"{inputTypeDocLink}\"{(RequiresLinkTarget(typeName) ? " target=\"_parent\"" : "")}>{GetTypeDisplayName(property.PropertyType, false)}</a>></div>"); } } else { sb.Append($"<div class=\"parameterName\">-{property.Name} <{GetTypeDisplayName(property.PropertyType, false)}></div>"); } sb.Append($"<div class=\"parameterDescription\">{property.PowershellWebDocumentation}</div>"); InspectParameter(property, out var isRequiredForParameterSets, out var pipelineInput, out var position, out var aliases); sb.Append("<div class=\"parameterAttributes\"><table>"); sb.Append($"<tr><td class=\"col1\">Required?</td><td class=\"col2\">{FormatIsRequired(isRequiredForParameterSets)}</td></tr>"); sb.Append($"<tr><td class=\"col1\">Position?</td><td class=\"col2\">{position}</td></tr>"); //sb.AppendFormat("<tr><td class=\"col1\">Default value</td><td class=\"col2\">{0}</td></tr>", ); sb.Append($"<tr><td class=\"col1\">Accept pipeline input?</td><td class=\"col2\">{pipelineInput}</td></tr>"); //sb.AppendFormat("<tr><td class=\"col1\">Accept wildcard characters?</td><td class=\"col2\">{0}</td></tr>", ); if (aliases.Length > 0) { sb.AppendFormat($"<tr><td class=\"col1\">Aliases</td><td class=\"col2\">{string.Join(", ", aliases)}</td></tr>"); } sb.Append("</table></div>"); sb.Append("</div>"); } if (sb.Length != 0) { writer.AddPageElement(pageElementKey, sb.ToString()); } }
private void WriteParameters(CmdletPageWriter writer, string cmdletName, IEnumerable <SimplePropertyInfo> allProperties) { var sb = new StringBuilder(); // Microsoft cmdlets list the parameters in alpha order here, so do the same (leaving metadata/paging // params in the correct order) foreach (var property in allProperties.OrderBy(p => p.Name)) { sb.Append("<div class=\"parameter\">"); var typeName = GetTypeDisplayName(property.PropertyType, true); var inputTypeDocLink = PredictHtmlDocsLink(typeName); if (!string.IsNullOrEmpty(inputTypeDocLink)) { sb.AppendFormat("<div class=\"parameterName\">-{0} <<a href=\"{1}\"{2}>{3}</a>></div>", property.Name, inputTypeDocLink, RequiresLinkTarget(typeName) ? " target=\"_blank\"" : "", GetTypeDisplayName(property.PropertyType, false)); } else { sb.AppendFormat("<div class=\"parameterName\">-{0} <{1}></div>", property.Name, GetTypeDisplayName(property.PropertyType, false)); } sb.AppendFormat("<div class=\"parameterDescription\">{0}</div>", property.PowershellWebDocumentation); InspectParameter(property, out var isRequiredForParameterSets, out var pipelineInput, out var position, out var aliases); sb.Append("<div class=\"parameterAttributes\"><table>"); sb.AppendFormat("<tr><td class=\"col1\">Required?</td><td class=\"col2\">{0}</td></tr>", FormatIsRequired(isRequiredForParameterSets)); sb.AppendFormat("<tr><td class=\"col1\">Position?</td><td class=\"col2\">{0}</td></tr>", position); //sb.AppendFormat("<tr><td class=\"col1\">Default value</td><td class=\"col2\">{0}</td></tr>", ); sb.AppendFormat("<tr><td class=\"col1\">Accept pipeline input?</td><td class=\"col2\">{0}</td></tr>", pipelineInput); //sb.AppendFormat("<tr><td class=\"col1\">Accept wildcard characters?</td><td class=\"col2\">{0}</td></tr>", ); if (aliases.Length > 0) { sb.AppendFormat("<tr><td class=\"col1\">Aliases</td><td class=\"col2\">{0}</td></tr>", string.Join(", ", aliases)); } sb.Append("</table></div>"); sb.Append("</div>"); } if (sb.Length == 0) { sb.Append("This cmdlet has no parameters specific to its operation."); } writer.AddPageElement(CmdletPageWriter.ParametersElementKey, sb.ToString()); }
private void WriteRelatedLinks(CmdletPageWriter writer, string serviceAbbreviation, string cmdletName) { var sb = new StringBuilder(); // putting common credential and region parameters into a related link is the simplest // approach, but only do it for service cmdlets if (!serviceAbbreviation.Equals("Common", StringComparison.Ordinal)) { XmlDocument document; if (LinksCache.TryGetValue(serviceAbbreviation, out document)) { ConstructLinks(sb, document, "*"); ConstructLinks(sb, document, cmdletName); } } // Add link for User Guide to all cmdlets AppendLink(sb, "AWS Tools for PowerShell User Guide", "http://docs.aws.amazon.com/powershell/latest/userguide/"); writer.AddPageElement(CmdletPageWriter.RelatedLinksElementKey, sb.ToString()); }
/// <summary> /// If the cmdlet is a service cmdlet, or is one of our common cmdlets that supports credential /// and/or region parameters, add in the relevant common parameters section /// </summary> /// <param name="writer"></param> /// <param name="addCredentials"></param> /// <param name="addRegion"></param> private void WriteCommonParameters(CmdletPageWriter writer, Type cmdletType, string cmdletName) { if (cmdletType.IsSubclassOf(ServiceCmdletBaseClass)) { var sb = new StringBuilder(); sb.AppendLine("<div class=\"sectionbody\">"); sb.AppendLine("<div class=\"parameters\">"); sb.Append("<div class=\"commonparameters\">"); // right now all service cmdlets have credential and region parameters sb.Append(CredentialParametersSnippet); sb.Append(RegionParametersSnippet); sb.Append("</div>"); sb.AppendLine("</div>"); sb.AppendLine("</div>"); writer.AddPageElement(CmdletPageWriter.CommonParametersElementKey, sb.ToString()); } }
private static void WriteSyntax(CmdletPageWriter writer, string cmdletName, CmdletParameterSetPartitions parameterSetPartitioning) { var sb = new StringBuilder(); if (parameterSetPartitioning.HasNamedParameterSets) { var sets = parameterSetPartitioning.NamedParameterSets; foreach (var set in sets) { AppendSyntaxChart(cmdletName, set, parameterSetPartitioning, sb); } } else { AppendSyntaxChart(cmdletName, CmdletParameterSetPartitions.AllSetsKey, parameterSetPartitioning, sb); } writer.AddPageElement(CmdletPageWriter.SyntaxElementKey, sb.ToString()); }
private void WriteOutputs(CmdletPageWriter writer, IEnumerable <object> outputAttributes) { var sb = new StringBuilder(); // attributing describing outputs means we don't need to worry about detecting sb.Length > 0 on exit foreach (var outputAttribute in outputAttributes) { var attributeType = outputAttribute.GetType(); var returnType = attributeType.GetProperty("ReturnType").GetValue(outputAttribute, null) as string; var description = attributeType.GetProperty("Description").GetValue(outputAttribute, null) as string; sb.Append("<div class=\"output\">"); if (!string.IsNullOrEmpty(returnType)) { returnType = TypeNameRegex.Replace(returnType, (match) => ChangeTypeNameStringIntoLink(match.Value)); sb.Append($"<div class=\"outputType\">{returnType}</div>"); } sb.Append($"<div class=\"outputDescription\">{WebUtility.HtmlEncode(description)}</div></div>"); sb.Append("</div>"); } writer.AddPageElement(CmdletPageWriter.OutputsElementKey, sb.ToString()); }
private void WriteInputs(CmdletPageWriter writer, IEnumerable <SimplePropertyInfo> allProperties) { var sb = new StringBuilder(); foreach (var simplePropertyInfo in allProperties) { if (simplePropertyInfo.PsParameterAttribute != null && IsMarkedValueFromPipeline(simplePropertyInfo.PsParameterAttribute)) { // if the input type has a predictable sdk/msdn html address, construct the link var inputTypeDocLink = PredictHtmlDocsLink(simplePropertyInfo.PropertyTypeName); sb.Append("<div class=\"inputType\">"); if (!string.IsNullOrEmpty(inputTypeDocLink)) { sb.AppendFormat("<a href=\"{0}\"{1}>{2}</a>", inputTypeDocLink, RequiresLinkTarget(simplePropertyInfo.PropertyTypeName) ? " target=\"_blank\"" : "", simplePropertyInfo.PropertyTypeName); } else { sb.Append(simplePropertyInfo.PropertyTypeName); } sb.Append("</div>"); sb.AppendFormat("<div class=\"inputDescription\">You can pipe a {0} object to this cmdlet for the {1} parameter.</div>", GetTypeDisplayName(simplePropertyInfo.PropertyType, false), simplePropertyInfo.CmdletParameterName); } } if (sb.Length == 0) { sb.Append("This cmdlet does not accept pipeline input."); } writer.AddPageElement(CmdletPageWriter.InputsElementKey, sb.ToString()); }
protected override void GenerateHelper() { base.GenerateHelper(); if (string.IsNullOrEmpty(SDKHelpRoot)) { SDKHelpRoot = "http://docs.aws.amazon.com/sdkfornet/v3/apidocs/"; } else if (!SDKHelpRoot.EndsWith("/")) { SDKHelpRoot = SDKHelpRoot + "/"; } Console.WriteLine("Generating web help documentation:"); Console.WriteLine(".... SDK help base URI set to {0}", SDKHelpRoot); Console.WriteLine(".... writing doc output to {0}", OutputFolder); var buildLogsPath = Path.Combine(this.Options.RootPath, "logs"); if (!Directory.Exists(buildLogsPath)) { Directory.CreateDirectory(buildLogsPath); } var logFile = Path.Combine(buildLogsPath, Name + ".dll-WebHelp.log"); var oldWriter = Console.Out; try { using (var consoleWriter = new StreamWriter(File.OpenWrite(logFile))) { Console.SetOut(consoleWriter); CleanWebHelpOutputFolder(OutputFolder); CopyWebHelpStaticFiles(OutputFolder); CreateVersionInfoFile(Path.Combine(OutputFolder, "items")); var tocWriter = new TOCWriter(Options, OutputFolder); tocWriter.AddFixedSection(); Parallel.ForEach(CmdletTypes, (cmdletType) => { var(moduleName, serviceName) = DetermineCmdletServiceOwner(cmdletType); var cmdletInfo = InspectCmdletAttributes(cmdletType); string synopsis = null; if (cmdletInfo.AWSCmdletAttribute == null) { Console.WriteLine("Unable to find AWSCmdletAttribute for type " + cmdletType.FullName); } else { var cmdletReturnAttributeType = cmdletInfo.AWSCmdletAttribute.GetType(); synopsis = cmdletReturnAttributeType.GetProperty("Synopsis").GetValue(cmdletInfo.AWSCmdletAttribute, null) as string; } foreach (var cmdletAttribute in cmdletInfo.CmdletAttributes) { var typeDocumentation = DocumentationUtils.GetTypeDocumentation(cmdletType, AssemblyDocumentation); typeDocumentation = DocumentationUtils.FormatXMLForPowershell(typeDocumentation, true); Console.WriteLine($"Cmdlet = {cmdletType.FullName}"); Console.WriteLine($"Documentation = {typeDocumentation}"); var cmdletName = cmdletAttribute.VerbName + "-" + cmdletAttribute.NounName; var allProperties = GetRootSimpleProperties(cmdletType); var parameterPartitioning = new CmdletParameterSetPartitions(allProperties, cmdletAttribute.DefaultParameterSetName); var serviceAbbreviation = GetServiceAbbreviation(cmdletType); var cmdletPageWriter = new CmdletPageWriter(Options, OutputFolder, serviceName, moduleName, cmdletName); WriteDetails(cmdletPageWriter, typeDocumentation, synopsis, cmdletInfo.AWSCmdletAttribute); WriteSyntax(cmdletPageWriter, cmdletName, parameterPartitioning); WriteParameters(cmdletPageWriter, cmdletName, allProperties, false); WriteParameters(cmdletPageWriter, cmdletName, allProperties, true); WriteOutputs(cmdletPageWriter, cmdletInfo.AWSCmdletOutputAttributes); WriteNotes(cmdletPageWriter); WriteExamples(cmdletPageWriter, cmdletName); WriteRelatedLinks(cmdletPageWriter, serviceAbbreviation, cmdletName); cmdletPageWriter.Write(); lock (tocWriter) { var legacyAlias = InspectForLegacyAliasAttribution(moduleName, cmdletName, cmdletInfo.AWSCmdletAttribute); tocWriter.AddServiceCmdlet(moduleName, serviceName, cmdletName, cmdletPageWriter.GetTOCID(), synopsis, legacyAlias); } } }); tocWriter.Write(); WriteLegacyAliasesPage(); } } finally { Console.SetOut(oldWriter); } }
private void WriteExamples(CmdletPageWriter writer, string cmdletName) { XmlDocument document; // lack of examples will be reported in the logs by the native help generator if (!ExamplesCache.TryGetValue(cmdletName, out document)) { return; } var set = document.SelectSingleNode("examples"); if (set == null) { return; } var sb = new StringBuilder(); int exampleIndex = 1; var examples = set.SelectNodes("example"); foreach (XmlNode example in examples) { sb.AppendFormat("<h4>Example {0}</h4>", exampleIndex); sb.Append("<pre class=\"example\">"); var code = example.SelectSingleNode("code"); if (code == null) { Logger.LogError("Unable to find examples <code> tag for cmdlet " + cmdletName); } var codeSample = code.InnerText.Trim('\r', '\n'); codeSample = codeSample.Replace(Environment.NewLine, "<br/>"); sb.AppendFormat("<div class=\"code\">{0}</div>", codeSample); var description = example.SelectSingleNode("description"); if (description == null) { Logger.LogError("Unable to find examples <description> tag for cmdlet " + cmdletName); } // use InnerXml here to allow for <br/> and other layout format tags, these get stripped // if we use InnerText var innerXml = description.InnerXml; // convert <url>link</url> elements to anchors (pshelp strips the tags to leave the link) /*if (innerXml.Contains("<href>")) * { * }*/ sb.AppendFormat("<div class=\"description\">{0}</div>", innerXml); sb.Append("</pre>"); exampleIndex++; } writer.AddPageElement(CmdletPageWriter.ExamplesElementKey, sb.ToString()); }
private static void WriteNotes(CmdletPageWriter writer) { }