/// <summary> /// Renders the <see cref="ExceptionDoc"/> element to string containing the markup provided by <paramref name="markupProvider"/> /// </summary> /// <remarks> /// Builds the link with the reference according to the <c>cref</c> attribute value. The value represents the Documentation ID /// that can be matched to the information got during the code analysis or to build the link to MS API reference for the "MS objects". /// First, it tries to resolve the <see cref="Member"/> in code being documented (internal link). If not successful, tries to look for /// the <c>cref</c> (Documentation ID) in the MS API documentation if allowed/available (see <see cref="MsApiDocEngine"/> for details) /// <para> /// The link text is the the name of linked entity when using internal <see cref="IMarkupProvider.Link(string,net.adamec.dev.markupdoc.CodeModel.Member)"/> /// or the <c>cref</c> without the leading type information when rendering . /// When the link is not constructed ("target unknown"), the <c>cref</c> value without the leading type information is rendered in italic /// </para> /// <para> /// The <exception> element is then rendered as <see cref="IMarkupProvider.DescriptionListItem"/> where ///<c>Term</c> is the link and <c>Description</c> is the fully trimmed element content. /// Important: it returns description list item, so must be encapsulated on higher level !!! /// </para> /// </remarks> /// <param name="markupProvider"><see cref="IMarkupProvider"/> allowing using the markup within the rendered content</param> /// <param name="member">Code model <see cref="Member"/> to render the XML Documentation Comment for</param> /// <param name="trim">Flag whether to (full) trim the rendered content</param> /// <returns>Rendered content of <exception> element of XML Documentation Comments. /// Important: it returns description list item, so must be encapsulated on higher level !!!</returns> ///<seealso cref="MsApiDocEngine"/> /// <seealso cref="MsApiDocOptions"/> protected override string RenderElement(IMarkupProvider markupProvider, Member member, bool trim = true) { //for exception always render both Ref(link if available) AND content //content var content = base.RenderElement(markupProvider, member, trim); //ref string exceptionRef; if (member.Root.AllMembersByDocId.TryGetValue(Ref, out var refMember)) { exceptionRef = markupProvider.Link(refMember.Name, refMember); } else { //Try to get the MS API link from reference var msLink = MsApiDocEngine.GetLink(Ref); //Got the MS link, so use external link // ReSharper disable once ConvertIfStatementToConditionalTernaryExpression if (msLink != null) { exceptionRef = markupProvider.ExternalLink(Ref.Substring(2), msLink); } else { //No link - Ref without leading "ref type" exceptionRef = markupProvider.Italic(Ref.Substring(2)); } } //output return(markupProvider.DescriptionListItem(exceptionRef, content)); }
/// <summary> /// Renders the element having the <c>cref</c> attribute to string containing the markup provided by <paramref name="markupProvider"/> /// </summary> /// <remarks> /// Builds the link with the reference according to the <c>cref</c> attribute value. The value represents the Documentation ID /// that can be matched to the information got during the code analysis or to build the link to MS API reference for the "MS objects". /// First, it tries to resolve the <see cref="Member"/> in code being documented (internal link). If not successful, tries to look for /// the <c>cref</c> (Documentation ID) in the MS API documentation if allowed/available (see <see cref="MsApiDocEngine"/> for details) /// <para> /// The link text is the rendered trimmed content of the tag if available, /// the name of linked entity when using internal <see cref="IMarkupProvider.Link(string,net.adamec.dev.markupdoc.CodeModel.Member)"/> /// or the <c>cref</c> without the leading type information when rendering <see cref="IMarkupProvider.ExternalLink"/>. /// When the link is not constructed ("target unknown"), the <c>cref</c> value without the leading type information is rendered in italic /// </para> /// </remarks> /// <param name="markupProvider"><see cref="IMarkupProvider"/> allowing using the markup within the rendered content</param> /// <param name="member">Code model <see cref="Member"/> to render the XML Documentation Comment for</param> /// <param name="trim">Flag whether to (full) trim the rendered content</param> /// <returns>Rendered content of element of XML Documentation Comments</returns> ///<seealso cref="MsApiDocEngine"/> /// <seealso cref="MsApiDocOptions"/> protected override string RenderElement(IMarkupProvider markupProvider, Member member, bool trim = true) //used for links { // ReSharper disable once RedundantArgumentDefaultValue var content = base.RenderElement(markupProvider, member, true); //always trim content for links if (string.IsNullOrEmpty(Ref)) { return(content); } //Return Ref to existing member as link, if available. If no content provided, use the member's name if (member.Root.AllMembersByDocId.TryGetValue(Ref, out var refMember)) { return(markupProvider.Link(!string.IsNullOrEmpty(content) ? content : refMember.Name, refMember)); } //Try to get the MS API link from reference var msLink = MsApiDocEngine.GetLink(Ref); //Got the MS link, so return external link if (msLink != null) { return(markupProvider.ExternalLink(!string.IsNullOrEmpty(content) ? content : Ref.Substring(2), msLink)); } //No link, return content if available otherwise Ref without leading "ref type" return(!string.IsNullOrEmpty(content) ? content : markupProvider.Italic(Ref.Substring(2))); }
/// <summary> /// Runs the documentation building logic /// </summary> /// <param name="projectFile">Project file of C# project to build the documentation for</param> /// <returns>Async task</returns> public async Task RunAsync(string projectFile) { if (string.IsNullOrEmpty(projectFile)) { throw new ArgumentNullException(nameof(projectFile)); } if (!File.Exists(projectFile)) { throw new ArgumentException($"Project file {projectFile} doesn't exist"); } var projectDir = new FileInfo(projectFile).DirectoryName; if (projectDir == null) { throw new Exception($"Can't get the project directory from {projectFile}"); } //Read MS API local documentation to get the links to MS API online documentation MsApiDocEngine.ReadLocalDoc(); //Prepare add-ons var addOns = GetAddOns(); //Build code model var root = await ModelBuilder.BuildFromProjectSourcesAsync(projectFile, addOns); //Prepare for the output var targetBase = OutputOptions.Target; //full name w/o extension if (string.IsNullOrEmpty(targetBase)) { targetBase = Path.Combine(projectDir, "doc"); //if not set, proj dir will be used and file doc.html/doc.md } var targetDir = new FileInfo(targetBase).DirectoryName; var targetFileBase = new FileInfo(targetBase).Name; if (OutputOptions.SplitNs) { root.ProcessingInfo.SplitFileType = SplitTypeEnum.Namespace; } if (OutputOptions.SplitType) { root.ProcessingInfo.SplitFileType = SplitTypeEnum.Type; } root.ProcessingInfo.BaseMainFile = targetFileBase; //Generate markup outputs if (OutputOptions.Markdown) { var writer = new MarkupGenerator( // ReSharper disable once AssignNullToNotNullAttribute Path.Combine(targetDir, $"{targetFileBase}.{OutputOptions.MarkdownExtension}"), root, new MarkdownMarkupProvider(OutputOptions)); await writer.WriteModelAsync(OutputOptions.Title); } if (OutputOptions.Html) { var writer = new MarkupGenerator( // ReSharper disable once AssignNullToNotNullAttribute Path.Combine(targetDir, $"{targetFileBase}.{OutputOptions.HtmlExtension}"), root, new HtmlMarkupProvider(OutputOptions)); await writer.WriteModelAsync(OutputOptions.Title); } }