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} &lt;<a href=\"{inputTypeDocLink}\"{(RequiresLinkTarget(typeName) ? " target=\"blank\" rel=\"noopener noreferrer\"" : "")}>{GetTypeDisplayName(property.PropertyType, false)}</a>&gt;</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} &lt;<a href=\"{inputTypeDocLink}\"{(RequiresLinkTarget(typeName) ? " target=\"_parent\"" : "")}>{GetTypeDisplayName(property.PropertyType, false)}</a>&gt;</div>");
                    }
                }
                else
                {
                    sb.Append($"<div class=\"parameterName\">-{property.Name} &lt;{GetTypeDisplayName(property.PropertyType, false)}&gt;</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());
            }
        }
Example #3
0
        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} &lt;<a href=\"{1}\"{2}>{3}</a>&gt;</div>",
                                    property.Name,
                                    inputTypeDocLink,
                                    RequiresLinkTarget(typeName) ? " target=\"_blank\"" : "",
                                    GetTypeDisplayName(property.PropertyType, false));
                }
                else
                {
                    sb.AppendFormat("<div class=\"parameterName\">-{0} &lt;{1}&gt;</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());
        }
Example #5
0
        /// <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());
        }
Example #8
0
        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)
 {
 }