/// <summary>
        /// Create the template output
        /// </summary>
        public virtual string TransformText()
        {
            this.Write("\r\n");
            this.Write("\r\n");
            
            #line 15 "D:\Github\SharpDox.Plugins.Html\src\SharpDox.Plugins.Html\Templates\Repository\DocumentationData.tt"
 var documentation = new List<string>();
if(Documentation.Summary.Count > 0) {
	documentation.Add(string.Format("\"summary\":\"{0}\"", CommonMarkConverter.Convert(Documentation.Summary.ToMarkdown(StepInput.SDProject.Tokens).Transform(Helper.TransformLinkToken)).ToObjectString()));
} 
if(Documentation.Remarks.Count > 0) {
	documentation.Add(string.Format("\"remarks\":\"{0}\"", CommonMarkConverter.Convert(Documentation.Remarks.ToMarkdown(StepInput.SDProject.Tokens).Transform(Helper.TransformLinkToken)).ToObjectString()));
}
if(Documentation.Example.Count > 0) {
	documentation.Add(string.Format("\"example\":\"{0}\"", CommonMarkConverter.Convert(Documentation.Example.ToMarkdown(StepInput.SDProject.Tokens).Transform(Helper.TransformLinkToken)).ToObjectString()));
}
if(Documentation.Returns.ContainsKey("default")) {
	documentation.Add(string.Format("\"returns\":\"{0}\"", CommonMarkConverter.Convert(Documentation.Returns["default"].ToMarkdown(StepInput.SDProject.Tokens).Transform(Helper.TransformLinkToken)).ToObjectString()));
}
if(Documentation.Exceptions.Count > 0) {
	documentation.Add(string.Format("\"exceptions\":[{0}]", 
				string.Join(",", Documentation.Exceptions.Select(exception => 
					string.Format("{{\"key\": \"{0}\",\"value\": \"{1}\"}}", exception.Key, 
					CommonMarkConverter.Convert(exception.Value.ToMarkdown(StepInput.SDProject.Tokens).Transform(Helper.TransformLinkToken)).ToObjectString())))));
}
if(Documentation.Params.Count > 0) {
	documentation.Add(string.Format("\"params\":[{0}]", 
				string.Join(",", Documentation.Params.Select(param => 
					string.Format("{{\"key\": \"{0}\",\"value\": \"{1}\"}}", param.Key, 
					CommonMarkConverter.Convert(param.Value.ToMarkdown(StepInput.SDProject.Tokens).Transform(Helper.TransformLinkToken)).ToObjectString())))));
}
if(Documentation.TypeParams.Count > 0) {
	documentation.Add(string.Format("\"params\":[{0}]", 
				string.Join(",", Documentation.TypeParams.Select(typeParam => 
					string.Format("{{\"key\": \"{0}\",\"value\": \"{1}\"}}", typeParam.Key, 
					CommonMarkConverter.Convert(typeParam.Value.ToMarkdown(StepInput.SDProject.Tokens).Transform(Helper.TransformLinkToken)).ToObjectString())))));	
}
if(Documentation.SeeAlsos.Count > 0 ){
	var seeAlsos = new List<string>();
	foreach(var sdToken in Documentation.SeeAlsos){
		var seeAlso = (SDSeeToken)sdToken;
		seeAlsos.Add(string.Format("{{\"type\":\"type\", \"id\":\"{0}\", \"name\":\"{1}\"}}", seeAlso.Identifier, seeAlso.Name));		
    }
	documentation.Add(string.Format("\"seeAlsos\":[{0}]", string.Join(",", seeAlsos)));
} 
            
            #line default
            #line hidden
            this.Write("\r\n");
            
            #line 55 "D:\Github\SharpDox.Plugins.Html\src\SharpDox.Plugins.Html\Templates\Repository\DocumentationData.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(string.Join(",", documentation)));
            
            #line default
            #line hidden
            this.Write("\r\n\r\n\r\n");
            return this.GenerationEnvironment.ToString();
        }
예제 #2
0
        /// <summary>
        /// Create the template output
        /// </summary>
        public virtual string TransformText()
        {
            this.Write("\r\n");
            this.Write("\r\n{\r\n\t");
            
            #line 19 "D:\Github\SharpDox.Plugins.Html\src\SharpDox.Plugins.Html\Templates\Repository\MemberData.tt"

	var properties = new List<string>();
	properties.Add($"\"id\": \"{Member.Identifier}\"");
	properties.Add($"\"urlId\": \"{Member.Identifier.RemoveIllegalHtmlIdChars()}\"");
	properties.Add($"\"type\": \"{MemberType}\""); 
	properties.Add($"\"accessibility\": \"{Member.Accessibility}\"");

	if(Member is SDMethod) {
		var sdMethod = (SDMethod)Member;
		properties.Add($"\"name\": \"{sdMethod.Signature}\"");

		if(!sdMethod.IsSequenceDiagramEmpty()) {
			properties.Add($"\"diagramId\": \"{sdMethod.Guid}\"");
			properties.Add($"\"sequenceDiagram\": \"{sdMethod.GetSequenceDiagram(Repository).ToSvg().Transform(Helper.TransformLinkToken).ToObjectString()}\"");
		}
	} else {
		properties.Add($"\"name\": \"{Member.Name}\"");
	}

	if(Member is SDField && !string.IsNullOrEmpty(((SDField)Member).ConstantValue)) {
		properties.Add($"\"constantValue\": \"{((SDField)Member).ConstantValue.ToObjectString()}\"");
	}

	if(Member.Region != null){
		properties.Add($"\"region\": {{\"start\": \"{Member.Region.StartLine}\", \"end\": \"{Member.Region.EndLine}\", \"filename\": \"{Member.Region.Filename.ToObjectString()}\"}}");
	}	

	var documentation = Member.Documentations.GetElementOrDefault(StepInput.CurrentLanguage);
	if(documentation != null){
		var documentationTemplate = new DocumentationData { Documentation = documentation };
		var documentationText = documentationTemplate.TransformText();
		if(!string.IsNullOrWhiteSpace(documentationText)) properties.Add(documentationText);
	}

	properties.Add($"\"syntax\": \"{Member.Syntax}\"");
	properties.Add($"\"linkedSyntax\": \"{Member.SyntaxTemplate.Transform(Helper.TransformLinkToken).ToObjectString()}\"");
	
            
            #line default
            #line hidden
            this.Write("\t");
            
            #line 56 "D:\Github\SharpDox.Plugins.Html\src\SharpDox.Plugins.Html\Templates\Repository\MemberData.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(string.Join(",", properties)));
            
            #line default
            #line hidden
            this.Write("\t\t\r\n}\r\n\r\n");
            return this.GenerationEnvironment.ToString();
        }
        public IEnumerable<NewsData> GetAllWithoutContent()
        {
            var newsList = new List<NewsData>();

            var fileProvider = _hostingEnvironment.WebRootFileProvider;
            var directoryContents = fileProvider.GetDirectoryContents(_newsPath).Where(x => x.Name.EndsWith(".json"));

            foreach (var directoryContent in directoryContents)
            {
                newsList.Add(GetNewsFromJsonFile(directoryContent));
            }

            return newsList;
        }
예제 #4
0
 public static List<string> LoadPreviousExtensionsChangelog()
 {
     var html = new List<string> {"<h1>Changelogs</h1>"};
     using (new HourGlass())
     {
         var webClient = new WebClient();
         WebClientHelper.SetHeaders(webClient);
         var releases =
             JsonConvert.DeserializeObject<List<GitHubVersion>>(
                 webClient.DownloadString("https://api.github.com/repos/zachsaw/MPDN_Extensions/releases"));
         foreach (var gitHubVersion in releases)
         {
             html.Add(string.Format("<h2>{0}</h2>", gitHubVersion.tag_name));
             html.Add(CommonMarkConverter.Convert(gitHubVersion.body));
         }
     }
     return html;
 }
        public IEnumerable<NewsData> GetAll()
        {
            var newsList = new List<NewsData>();
            newsList.AddRange(GetAllWithoutContent());

            var fileProvider = _hostingEnvironment.WebRootFileProvider;
            var directoryContents = fileProvider.GetDirectoryContents(_newsPath).Where(x => x.Name.EndsWith("_content.md"));

            foreach (var news in newsList)
            {
                var contentFileForNews = directoryContents.Single(x => x.Name == $"{news.Id}_content.md");
                string htmlContent = GetHtmlContentFromMarkdownFile(contentFileForNews);

                news.Content = htmlContent;
            }

            return newsList;
        }
예제 #6
0
        /// <summary>
        /// Initializes a new instance of <see cref="ProjbookHtmlFormatter"/>.
        /// </summary>
        /// <param name="contextName">Initializes the required <see cref="ContextName"/></param>
        /// <param name="target">Initializes the required text writer used as output.</param>
        /// <param name="settings">Initializes the required common mark settings used by the formatting.</param>
        /// <param name="sectionTitleBase">Initializes the section title base.</param>
        /// <param name="snippetDictionary">Initializes the snippet directory.</param>
        /// <param name="snippetReferencePrefix">Initializes the snippet reference prefix.</param>
        public ProjbookHtmlFormatter(string contextName, TextWriter target, CommonMarkSettings settings, int sectionTitleBase, Dictionary<Guid, Extension.Model.Snippet> snippetDictionary, string snippetReferencePrefix)
            : base(target, settings)
        {
            // Data validation
            Ensure.That(() => contextName).IsNotNullOrWhiteSpace();
            Ensure.That(target is StreamWriter).IsTrue();
            Ensure.That(() => sectionTitleBase).IsGte(0);
            Ensure.That(() => snippetDictionary).IsNotNull();
            Ensure.That(() => snippetReferencePrefix).IsNotNull();

            // Initialize
            this.ContextName = contextName;
            this.pageBreak = new List<PageBreakInfo>();
            this.writer = target as StreamWriter;
            this.sectionTitleBase = sectionTitleBase;
            this.snippetDictionary = snippetDictionary;
            this.snippetReferencePrefix = snippetReferencePrefix;
        }
예제 #7
0
        //[HttpPost]
        public async Task<IActionResult> Viewer(IFormFile file = null, string gitHubUrl = "")
        {
            var fileContent = string.Empty;

            //get file content as string
            if (file != null)
            {
                //read incoming file to a string
                using (var reader = new StreamReader(file.OpenReadStream()))
                {
                    fileContent = reader.ReadToEnd();
                }
            }
            else if (!string.IsNullOrEmpty(gitHubUrl))
            {
                //check if gitHubUrl is base 64, decoded if it is
                gitHubUrl = DecodeBase64(gitHubUrl);

                //get file content from GitHUb
                fileContent = await GetGitHubFile(gitHubUrl);
            }
            else
            {
                //return back to index
                return RedirectToAction("Index");
            }

            //convert markdown file to array of html section strings
            var sections = ConvertFile(fileContent);

            //find and extract h1 for page title from array of html strings
            var title = GetTitle(sections);

            //enumerate HTML sections and construct array of slides for Owl Carousel
            List<string> slides = new List<string>();
            foreach (var section in sections)
            {
                var outputSb = new StringBuilder();

                //eliminate empty sections
                if (section.ToLower() != "<p></p>\r\n")
                {
                    //populate owl format carosel slides
                    outputSb.AppendLine("<div class=\"item\">");
                    outputSb.AppendLine(section);
                    outputSb.AppendLine("</div>");
                }

                //add slide to array
                slides.Add(outputSb.ToString());
            }

            //View model
            var viewModel = new Viewer()
            {
                Title = title,
                SlidesHtml = slides
            };

            return View(viewModel);
        }
예제 #8
0
 private string GetTitle(List<string> sections)
 {
     HtmlDocument agilityDoc = new HtmlDocument();
     var title = string.Empty;
     foreach (var section in sections)
     {
         agilityDoc.LoadHtml(section);
         title = agilityDoc.DocumentNode.Descendants("h1").Select(nd => nd.InnerText).FirstOrDefault();
         if (title != string.Empty) break;
     }
     return title;
 }
예제 #9
0
 public static List<string> LoadPreviousMpdnChangelog()
 {
     var html = new List<string>();
     using (new HourGlass())
     {
         var webClient = new WebClient();
         WebClientHelper.SetHeaders(webClient);
         var changelog = webClient.DownloadString(string.Format("{0}ChangeLog.txt", UpdateChecker.LatestFolderUrl));
         html.Add("<h1>Changelogs</h1>");
         foreach (var line in Regex.Split(changelog, "\r\n|\r|\n"))
         {
             if (line.Contains("Changelog") && Version.ContainsVersionString(line))
             {
                 html.Add(string.Format("<h2>{0}</h2><ol>", line));
             }
             else if (string.IsNullOrWhiteSpace(line))
             {
                 html.Add("</ol>");
             }
             else
             {
                 html.Add(string.Format("<li>{0}</li>", line));
             }
         }
     }
     return html;
 }
예제 #10
0
 /// <summary>
 /// Generates a file.
 /// </summary>
 /// <param name="templateName">The template name use as input.</param>
 /// <param name="outputFileHtml">The output html file.</param>
 /// <param name="configuration">The configuration to inject.</param>
 /// <param name="pages">The pages to inject.</param>
 private void GenerateFile(string templateName, string outputFileHtml, Configuration configuration, List<Model.Page> pages)
 {
     // Generate final documentation from the template using razor engine
     var fileConfiguration = new { Title = configuration.Title, Pages = pages };
     this.WriteFile(templateName, outputFileHtml, fileConfiguration);
 }
예제 #11
0
        public static List<string> ParseMpdnChangelog(List<string> changelog)
        {
            var lines = new List<string> {"<h1>Changelog</h1>", "<div id='changelog'><ol>"};

            lines.AddRange(
                changelog.Select(line => string.IsNullOrWhiteSpace(line) ? null : string.Format("<li>{0}</li>", line)));
            lines.Add("</ol></div>");
            return lines;
        }
예제 #12
0
        /// <summary>
        /// Generates documentation.
        /// </summary>
        /// <returns>The generation errors.</returns>
        public Model.GenerationError[] Generate(Configuration configuration)
        {
            // Initialize the list containing all generation errors
            List<Model.GenerationError> generationError = new List<Model.GenerationError>();

            // Ensure output directory exists
            if (!this.OutputDirectory.Exists)
            {
                this.OutputDirectory.Create();
            }

            // Process all pages
            List<Model.Page> pages = new List<Model.Page>();
            foreach (Page page in configuration.Pages)
            {
                // Compute the page id used as a tab id and page prefix for bookmarking
                string pageId = page.Path.Replace(".", string.Empty).Replace("/", string.Empty).Replace("\\", string.Empty);

                // Load the document
                Block document;

                // Process the page
                string pageFilePath = this.fileSystem.FileInfo.FromFileName(page.FileSystemPath).FullName;
                using (StreamReader reader = new StreamReader(this.fileSystem.File.Open(pageFilePath, FileMode.Open, FileAccess.Read, FileShare.Read)))
                {
                    document = CommonMarkConverter.ProcessStage1(reader);
                }

                // Process snippet
                CommonMarkConverter.ProcessStage2(document);
                Dictionary<Guid, Extension.Model.Snippet> snippetDictionary = new Dictionary<Guid, Extension.Model.Snippet>();
                foreach (var node in document.AsEnumerable())
                {
                    // Filter fenced code
                    if (node.Block != null && node.Block.Tag == BlockTag.FencedCode)
                    {
                        // Build extraction rule
                        string fencedCode = node.Block.FencedCodeData.Info;

                        // Do not trigger extraction if the fenced code is empty
                        if (string.IsNullOrWhiteSpace(fencedCode))
                        {
                            continue;
                        }

                        SnippetExtractionRule snippetExtractionRule = SnippetExtractionRule.Parse(fencedCode);

                        // Extract and inject snippet and the factory were able to create an extractor
                        if (null != snippetExtractionRule)
                        {
                            // Cleanup Projbook specific syntax
                            node.Block.FencedCodeData.Info = snippetExtractionRule.Language;

                            // Inject snippet
                            try
                            {
                                // Retrieve the extractor instance
                                ISnippetExtractor snippetExtractor;
                                if (!this.extractorCache.TryGetValue(snippetExtractionRule.TargetPath, out snippetExtractor))
                                {
                                    snippetExtractor = this.snippetExtractorFactory.CreateExtractor(snippetExtractionRule);
                                    this.extractorCache[snippetExtractionRule.TargetPath] = snippetExtractor;
                                }

                                // Look for the file in available source directories
                                FileSystemInfoBase fileSystemInfo = null;
                                DirectoryInfoBase[] directoryInfos = null;
                                if (TargetType.FreeText != snippetExtractor.TargetType)
                                {
                                    directoryInfos = this.ExtractSourceDirectories(this.CsprojFile);
                                    foreach (DirectoryInfoBase directoryInfo in directoryInfos)
                                    {
                                        // Get directory name
                                        string directoryName = directoryInfo.FullName;
                                        if (1 == directoryName.Length && Path.DirectorySeparatorChar == directoryName[0])
                                            directoryName = string.Empty;

                                        // Compute file full path
                                        string fullFilePath = this.fileSystem.Path.GetFullPath(this.fileSystem.Path.Combine(directoryName, snippetExtractionRule.TargetPath ?? string.Empty));
                                        switch (snippetExtractor.TargetType)
                                        {
                                            case TargetType.File:
                                                if (this.fileSystem.File.Exists(fullFilePath))
                                                {
                                                    fileSystemInfo = this.fileSystem.FileInfo.FromFileName(fullFilePath);
                                                }
                                                break;
                                            case TargetType.Folder:
                                                if (this.fileSystem.Directory.Exists(fullFilePath))
                                                {
                                                    fileSystemInfo = this.fileSystem.DirectoryInfo.FromDirectoryName(fullFilePath);
                                                }
                                                break;
                                        }

                                        // Stop lookup if the file system info is found
                                        if (null != fileSystemInfo)
                                        {
                                            break;
                                        }
                                    }
                                }

                                // Raise an error if cannot find the file
                                if (null == fileSystemInfo && TargetType.FreeText != snippetExtractor.TargetType)
                                {
                                    // Locate block line
                                    int line = this.LocateBlockLine(node.Block, page);

                                    // Compute error column: Index of the path in the fenced code + 3 (for the ``` prefix) + 1 (to be 1 based)
                                    int column = fencedCode.IndexOf(snippetExtractionRule.TargetPath) + 4;

                                    // Report error
                                    generationError.Add(new Model.GenerationError(
                                        sourceFile: page.Path,
                                        message: string.Format("Cannot find target '{0}' in any referenced project ({0})", snippetExtractionRule.TargetPath, string.Join(";", directoryInfos.Select(x => x.FullName))),
                                        line: line,
                                        column: column));
                                    continue;
                                }

                                // Extract the snippet
                                Extension.Model.Snippet snippet =
                                    TargetType.FreeText == snippetExtractor.TargetType
                                    ? snippetExtractor.Extract(null, snippetExtractionRule.TargetPath)
                                    : snippetExtractor.Extract(fileSystemInfo, snippetExtractionRule.Pattern);

                                // Reference snippet
                                Guid guid = Guid.NewGuid();
                                snippetDictionary[guid] = snippet;

                                // Inject reference as content
                                StringContent code = new StringContent();
                                string content = SNIPPET_REFERENCE_PREFIX + guid;
                                code.Append(content, 0, content.Length);
                                node.Block.StringContent = code;

                                // Change tag to html for node snippets
                                NodeSnippet nodeSnippet = snippet as NodeSnippet;
                                if (null != nodeSnippet)
                                {
                                    node.Block.Tag = BlockTag.HtmlBlock;
                                }
                            }
                            catch (SnippetExtractionException snippetExtraction)
                            {
                                // Locate block line
                                int line = this.LocateBlockLine(node.Block, page);

                                // Compute error column: Fenced code length - pattern length + 3 (for the ``` prefix) + 1 (to be 1 based)
                                int column = fencedCode.Length - snippetExtractionRule.Pattern.Length + 4;

                                // Report error
                                generationError.Add(new Model.GenerationError(
                                    sourceFile: page.Path,
                                    message: string.Format("{0}: {1}", snippetExtraction.Message, snippetExtraction.Pattern),
                                    line: line,
                                    column: column));
                            }
                            catch (System.Exception exception)
                            {
                                generationError.Add(new Model.GenerationError(
                                    sourceFile: page.Path,
                                    message: exception.Message,
                                    line: 0,
                                    column: 0));
                            }
                        }
                    }
                }

                // Write to output
                ProjbookHtmlFormatter projbookHtmlFormatter = null;
                MemoryStream documentStream = new MemoryStream();
                using (StreamWriter writer = new StreamWriter(documentStream))
                {
                    // Setup custom formatter
                    CommonMarkSettings.Default.OutputDelegate = (d, o, s) => (projbookHtmlFormatter = new ProjbookHtmlFormatter(pageId, o, s, configuration.SectionTitleBase, snippetDictionary, SNIPPET_REFERENCE_PREFIX)).WriteDocument(d);

                    // Render
                    CommonMarkConverter.ProcessStage3(document, writer);
                }

                // Initialize the pre section content
                string preSectionContent = string.Empty;

                // Retrieve page content
                byte[] pageContent = documentStream.ToArray();

                // Set the whole page content if no page break is detected
                if (projbookHtmlFormatter.PageBreak.Length == 0)
                {
                    preSectionContent = System.Text.Encoding.UTF8.GetString(pageContent);
                }

                // Compute pre section content from the position 0 to the first page break position
                if (projbookHtmlFormatter.PageBreak.Length > 0 && projbookHtmlFormatter.PageBreak.First().Position > 0)
                {
                    preSectionContent = this.StringFromByteArray(pageContent, 0, projbookHtmlFormatter.PageBreak.First().Position);
                }

                // Build section list
                List<Model.Section> sections = new List<Model.Section>();
                for (int i = 0; i < projbookHtmlFormatter.PageBreak.Length; ++i)
                {
                    // Retrieve the current page break
                    PageBreakInfo pageBreak = projbookHtmlFormatter.PageBreak[i];

                    // Extract the content from the current page break to the next one if any
                    string content = null;
                    if (i < projbookHtmlFormatter.PageBreak.Length - 1)
                    {
                        PageBreakInfo nextBreak = projbookHtmlFormatter.PageBreak[1 + i];
                        content = this.StringFromByteArray(pageContent, pageBreak.Position, nextBreak.Position - pageBreak.Position);
                    }

                    // Otherwise extract the content from the current page break to the end of the content
                    else
                    {
                        content = this.StringFromByteArray(pageContent, pageBreak.Position, pageContent.Length - pageBreak.Position);
                    }

                    // Create a new section and add to the known list
                    sections.Add(new Model.Section(
                        id: pageBreak.Id,
                        level: pageBreak.Level,
                        title: pageBreak.Title,
                        content: content));
                }

                // Add new page
                pages.Add(new Model.Page(
                    id: pageId,
                    title: page.Title,
                    preSectionContent: preSectionContent,
                    sections: sections.ToArray()));
            }

            // Html generation
            if (configuration.GenerateHtml)
            {
                try
                {
                    string outputFileHtml = this.fileSystem.Path.Combine(this.OutputDirectory.FullName, configuration.OutputHtml);
                    this.GenerateFile(configuration.TemplateHtml, outputFileHtml, configuration, pages);
                }
                catch (TemplateParsingException templateParsingException)
                {
                    generationError.Add(new Model.GenerationError(configuration.TemplateHtml, string.Format("Error during HTML generation: {0}", templateParsingException.Message), templateParsingException.Line, templateParsingException.Column));
                }
                catch (System.Exception exception)
                {
                    generationError.Add(new Model.GenerationError(configuration.TemplateHtml, string.Format("Error during HTML generation: {0}", exception.Message), 0, 0));
                }
            }

            // Pdf generation
            if (configuration.GeneratePdf && !this.SkipPdf)
            {
                try
                {
                    // Generate the pdf template
                    string outputFileHtml = this.fileSystem.Path.Combine(this.OutputDirectory.FullName, configuration.OutputPdf);
                    this.GenerateFile(configuration.TemplatePdf, outputFileHtml, configuration, pages);

            #if !NOPDF
                    // Compute file names
                    string outputPdf = this.fileSystem.Path.ChangeExtension(configuration.OutputPdf, ".pdf");
                    string outputFilePdf = this.fileSystem.Path.Combine(this.OutputDirectory.FullName, outputPdf);

                    // Prepare the converter
                    MultiplexingConverter pdfConverter = new MultiplexingConverter();
                    pdfConverter.ObjectSettings.Page = outputFileHtml;
                    pdfConverter.Error += (s, e) => {
                        generationError.Add(new Model.GenerationError(configuration.TemplatePdf, string.Format("Error during PDF generation: {0}", e.Value), 0, 0));
                    };

                    // Prepare file system if abstracted
                    bool requireCopyToFileSystem = !File.Exists(outputFileHtml);
                    try
                    {
                        // File system may be abstracted, this requires to copy the pdf generation file to the actual file system
                        // in order to allow wkhtmltopdf to process the generated html as input file
                        if (requireCopyToFileSystem)
                        {
                            File.WriteAllBytes(outputFileHtml, this.fileSystem.File.ReadAllBytes(outputFileHtml));
                        }

                        // Run pdf converter
                        using (pdfConverter)
                        using (Stream outputFileStream = this.fileSystem.File.Open(outputFilePdf, FileMode.Create, FileAccess.Write, FileShare.None))
                        {
                            try
                            {
                                byte[] buffer = pdfConverter.Convert();
                                outputFileStream.Write(buffer, 0, buffer.Length);
                            }
                            catch
                            {
                                // Ignore generation errors at that level
                                // Errors are handled by the error handling having the best description
                            }
                        }
                    }
                    finally
                    {
                        if (requireCopyToFileSystem && File.Exists(outputFileHtml))
                        {
                            File.Delete(outputFileHtml);
                        }
                    }
            #endif
                }
                catch (TemplateParsingException templateParsingException)
                {
                    generationError.Add(new Model.GenerationError(configuration.TemplatePdf, string.Format("Error during PDF generation: {0}", templateParsingException.Message), templateParsingException.Line, templateParsingException.Column));
                }
                catch (System.Exception exception)
                {
                    if (null != exception.InnerException && INCORRECT_FORMAT_HRESULT == exception.InnerException.HResult)
                    {
                        // Report detailed error message for wrong architecture loading
                        string runningArchitectureProccess = IntPtr.Size == 8 ? "x64" : "x86";
                        string otherRunningArchitectureProccess = IntPtr.Size != 8 ? "x64" : "x86";
                        generationError.Add(new Model.GenerationError(configuration.TemplatePdf, string.Format("Error during PDF generation: Could not load wkhtmltopdf for {0}. Try again running as a {1} process.", runningArchitectureProccess, otherRunningArchitectureProccess), 0, 0));
                    }
                    else
                    {
                        // Report unknown error
                        generationError.Add(new Model.GenerationError(configuration.TemplatePdf, string.Format("Error during PDF generation: {0}", exception.Message), 0, 0));
                    }
                }
            }

            // Return the generation errors
            return generationError.ToArray();
        }
예제 #13
0
        /// <summary>
        /// Generates the index page for the documentation.
        /// </summary>
        /// <param name="indexConfiguration">The index configuration.</param>
        /// <returns>The generation errors.</returns>
        public GenerationError[] GenerateIndex(IndexConfiguration indexConfiguration)
        {
            // Data validation
            Ensure.That(() => indexConfiguration).IsNotNull();

            // Try to generate the index html file
            List<GenerationError> generationError = new List<GenerationError>();
            try
            {
                string outputFileHtml = this.fileSystem.Path.Combine(this.OutputDirectory.FullName, indexConfiguration.Output);
                this.GenerateIndexFile(indexConfiguration.Template, outputFileHtml, indexConfiguration);
            }
            catch (TemplateParsingException templateParsingException)
            {
                generationError.Add(new Model.GenerationError(indexConfiguration.Template, string.Format("Error during HTML generation: {0}", templateParsingException.Message), templateParsingException.Line, templateParsingException.Column));
            }
            catch (System.Exception exception)
            {
                generationError.Add(new Model.GenerationError(indexConfiguration.Template, string.Format("Error during HTML generation: {0}", exception.Message), 0, 0));
            }

            // Return generation errors
            return generationError.ToArray();
        }
예제 #14
0
        /// <summary>
        /// Specializes block writing for anchor injection.
        /// For each formatted header we generate an anchor based on the context name, the header content and eventually add an integer suffix in order to prevent conflicts.
        /// </summary>
        /// <param name="block">The block to process.</param>
        /// <param name="isOpening">Define whether the block is opening.</param>
        /// <param name="isClosing">Defines whether the block is closing.</param>
        /// <param name="ignoreChildNodes">return whether the processing ignored child nodes.</param>
        protected override void WriteBlock(Block block, bool isOpening, bool isClosing, out bool ignoreChildNodes)
        {
            // Process block content
            if (null != block.StringContent)
            {
                // Read current block content
                string content = block.StringContent.TakeFromStart(block.StringContent.Length);

                // Detect snippet reference
                if (content.StartsWith(snippetReferencePrefix))
                {
                    // Fetch matching snippet
                    Extension.Model.Snippet snippet = snippetDictionary[Guid.Parse(content.Substring(snippetReferencePrefix.Length))];

                    // Render and write plain text snippet
                    PlainTextSnippet plainTextSnippet = snippet as PlainTextSnippet;
                    if (null != plainTextSnippet)
                    {
                        block.StringContent.Replace(plainTextSnippet.Text, 0, plainTextSnippet.Text.Length);
                    }

                    // Render and write node snippet
                    NodeSnippet nodeSnippet = snippet as NodeSnippet;
                    if (null != nodeSnippet)
                    {
                        // Render node as html
                        string renderedNode = Render(nodeSnippet.Node);

                        // Write rendering
                        block.StringContent.Replace(renderedNode, 0, renderedNode.Length);
                    }
                }
            }

            // Filter opening header
            if (isOpening && null != block && block.Tag == BlockTag.AtxHeading)
            {
                // Apply section title base
                block.Heading = new HeadingData(block.Heading.Level + this.sectionTitleBase);

                // Retrieve header content
                string headerContent;
                if (null != block.InlineContent && null != block.InlineContent.LiteralContent)
                {
                    // Read the whole content
                    Inline inline = block.InlineContent;
                    StringBuilder stringBuilder = new StringBuilder();
                    do
                    {
                        stringBuilder.Append(inline.LiteralContent);
                        inline = inline.NextSibling;
                    } while (null != inline);
                    headerContent = stringBuilder.ToString();
                }
                else
                {
                    headerContent = "unknown";
                }

                // Compute the anchor value
                string sectionId = headerContent.ToLower();
                sectionId = invalidTitleChars.Replace(string.Format("{0}-{1}", this.ContextName, sectionId), "-");

                // Detect anchor conflict
                if (sectionConflict.ContainsKey(sectionId))
                {
                    // Append the index
                    sectionId = string.Format("{0}-{1}", sectionId, ++sectionConflict[sectionId]);
                }

                // Flush the writer to move the stream position used during page break creation
                this.writer.Flush();

                // Add a new page break
                this.pageBreak.Add(new PageBreakInfo(sectionId, Math.Max(0, (int)block.Heading.Level), headerContent, this.writer.BaseStream.Position));

                // Initialize section conflict
                sectionConflict[sectionId] = 1;
            }

            // Read all paragraph inline strings in order to make table detectable
            List<string> tableParts = new List<string>();
            List<string[]> splittedTableParts = new List<string[]>();
            Match[] headerDelimiterMatches = null;
            if (isOpening && null != block && block.Tag == BlockTag.Paragraph)
            {
                Inline inline = block.InlineContent;
                while (null != inline)
                {
                    if (inline.Tag == InlineTag.String)
                    {
                        // Read and split line on '|'
                        tableParts.Add(inline.LiteralContent);
                        string line = inline.LiteralContent.Trim();
                        string[] lineParts = line.Split(new char[] { '|' }, StringSplitOptions.None).Select(x => x.Trim()).ToArray();

                        // At the third line of the same block, ensure we're processing a table before to continue table parsing
                        if (splittedTableParts.Count == 2)
                        {
                            // If the second line cannot be a header delimiter, break the table parsing
                            if (splittedTableParts[1].Any(x => string.IsNullOrWhiteSpace(x)) || (splittedTableParts[1].Length < 2 && !tableParts[1].Contains('|')))
                            {
                                break;
                            }

                            // Matches the second line as header delimiter and abort table parsing if the match fail
                            headerDelimiterMatches = splittedTableParts[1].Select(x => dashDelimiter.Match(x)).ToArray();
                            if (!headerDelimiterMatches.All(x => x.Success))
                            {
                                break;
                            }
                        }

                        // Define parts boundaries
                        int startPos = 0;
                        int numbber = lineParts.Length;

                        // Ignore the first part if the line starts with '|'
                        if ('|' == line.First())
                        {
                            ++startPos;
                            --numbber;
                        }

                        // Ignore the last part if the line ends with '|'
                        if ('|' == line.Last())
                        {
                            --numbber;
                        }

                        // Add the line to splitted parts
                        splittedTableParts.Add(lineParts.Skip(startPos).Take(numbber).ToArray());
                    }
                    inline = inline.NextSibling;
                }
            }

            // Process table rendering
            if (null != headerDelimiterMatches && splittedTableParts.Count > 2)
            {
                // Remove the delimiter
                splittedTableParts.RemoveAt(1);

                // Render table
                this.Write(@"<table class=""table"">");
                for (int i = 0; i < splittedTableParts.Count; ++i)
                {
                    // Render rows
                    this.Write("<tr>");

                    // Render cells
                    for (int j = 0; j < splittedTableParts[i].Length; ++j)
                    {
                        // Determine text alignment
                        string style = "text-left";
                        if (headerDelimiterMatches.Length > j && 0 < i)
                        {
                            Match match = headerDelimiterMatches[j];
                            if (":" == match.Groups[1].Value && ":" == match.Groups[2].Value)
                            {
                                style = "text-center";
                            }
                            else if ("" == match.Groups[1].Value && ":" == match.Groups[2].Value)
                            {
                                style = "text-right";
                            }
                        }

                        // Generate markup
                        string tag = 0 == i ? "th" : "td";
                        this.Write(string.Format(@"<{0} class=""{1}"">", tag, style));
                        this.Write(splittedTableParts[i][j]);
                        this.Write(string.Format("</{0}>", tag));
                    }

                    this.Write("</tr>");
                }
                this.Write("</table>");

                // Report rendering finished
                ignoreChildNodes = true;
                return;
            }

            // Trigger parent rendering for the default html rendering
            base.WriteBlock(block, isOpening, isClosing, out ignoreChildNodes);
        }
예제 #15
0
        /// <summary>
        /// Create the template output
        /// </summary>
        public virtual string TransformText()
        {
            this.Write("\r\n");
            this.Write("\r\n\"");
            
            #line 14 "D:\Github\SharpDox.Plugins.Html\src\SharpDox.Plugins.Html\Templates\Repository\NamespaceData.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(TargetFx.Name));
            
            #line default
            #line hidden
            this.Write("\": {\r\n\t\t\"name\": \"");
            
            #line 15 "D:\Github\SharpDox.Plugins.Html\src\SharpDox.Plugins.Html\Templates\Repository\NamespaceData.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Namespace.Fullname));
            
            #line default
            #line hidden
            this.Write("\",\r\n\t\t\"assembly\": \"");
            
            #line 16 "D:\Github\SharpDox.Plugins.Html\src\SharpDox.Plugins.Html\Templates\Repository\NamespaceData.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Namespace.Assemblyname));
            
            #line default
            #line hidden
            this.Write("\",\r\n\t\t\"description\": \"");
            
            #line 17 "D:\Github\SharpDox.Plugins.Html\src\SharpDox.Plugins.Html\Templates\Repository\NamespaceData.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Namespace.Descriptions.GetElementOrDefault(StepInput.CurrentLanguage) != null ?
						CommonMarkConverter.Convert(Namespace.Descriptions.GetElementOrDefault(StepInput.CurrentLanguage).Transform(Helper.TransformLinkToken)).ToObjectString()
						: string.Empty));
            
            #line default
            #line hidden
            this.Write("\", \r\n\t\t");
            
            #line 20 "D:\Github\SharpDox.Plugins.Html\src\SharpDox.Plugins.Html\Templates\Repository\NamespaceData.tt"
 if(Namespace.UsedBy.Count > 0) { 
            
            #line default
            #line hidden
            this.Write("\t\t\"usedBy\": [\r\n\t\t\t");
            
            #line 22 "D:\Github\SharpDox.Plugins.Html\src\SharpDox.Plugins.Html\Templates\Repository\NamespaceData.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(string.Join(",", Namespace.UsedBy.Select(usedBy => 
				string.Format("{{\"id\": \"{0}\",\"name\": \"{1}\"}}", usedBy.Identifier, usedBy.Fullname)))));
            
            #line default
            #line hidden
            this.Write("\r\n\t\t],\r\n\t\t");
            
            #line 25 "D:\Github\SharpDox.Plugins.Html\src\SharpDox.Plugins.Html\Templates\Repository\NamespaceData.tt"
 } if(Namespace.Uses.Count > 0) { 
            
            #line default
            #line hidden
            this.Write("\t\t\"uses\": [\r\n\t\t\t");
            
            #line 27 "D:\Github\SharpDox.Plugins.Html\src\SharpDox.Plugins.Html\Templates\Repository\NamespaceData.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(string.Join(",", Namespace.Uses.Select(use => 
				string.Format("{{\"id\": \"{0}\",\"name\": \"{1}\"}}", use.Identifier, use.Fullname)))));
            
            #line default
            #line hidden
            this.Write("\r\n\t\t], \r\n\t\t");
            
            #line 30 "D:\Github\SharpDox.Plugins.Html\src\SharpDox.Plugins.Html\Templates\Repository\NamespaceData.tt"
 } 
            
            #line default
            #line hidden
            this.Write("\t\t\"types\":[\r\n\t\t\t");
            
            #line 32 "D:\Github\SharpDox.Plugins.Html\src\SharpDox.Plugins.Html\Templates\Repository\NamespaceData.tt"
 var types = new List<string>();
			foreach(var sdType in Namespace.Types){
				var documentation = sdType.Documentations.GetElementOrDefault(StepInput.CurrentLanguage);
				var docString = documentation != null ? 
								CommonMarkConverter.Convert(documentation.Summary.ToMarkdown(StepInput.SDProject.Tokens).Transform(Helper.TransformLinkToken)).ToObjectString() :
								string.Empty;
				types.Add(string.Format("{{\"id\":\"{0}\",\"kind\":\"{1}\",\"accessibility\":\"{2}\",\"name\":\"{3}\",\"summary\":\"{4}\"}}",
							sdType.Identifier.RemoveIllegalPathChars(), sdType.Kind, sdType.Accessibility, sdType.Name, docString));
			} 
            
            #line default
            #line hidden
            this.Write("\t\t\t");
            
            #line 41 "D:\Github\SharpDox.Plugins.Html\src\SharpDox.Plugins.Html\Templates\Repository\NamespaceData.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(string.Join(",", types)));
            
            #line default
            #line hidden
            this.Write("\r\n\t\t]\r\n\t}\r\n\r\n");
            return this.GenerationEnvironment.ToString();
        }
예제 #16
0
        public static string Render(Game game, ActionResult result)
        {
            string body = "";

            if (game == null || game.CurrentAR == null || game.CurrentAR.Storylet == null)
                return "No storylet!";

            body += "<div class='storylet'>";

            body += string.Format("<h3>{0}</h3>\n", game.CurrentAR.Storylet.Title);

            foreach(var test in game.CurrentAR.Tests)
            {
                if (test != null && test.Test != null)
                {
                    var qual = Data.GetQuality(test.Test.QualityName);
                    if (qual != null)
                        body += string.Format("<p>You {0} a test of {1} {2}</p>\n", (test.Success) ? "succeeded" : "failed", qual.Title, test.Test.Value);
                }
            }

            body += CommonMarkConverter.Convert(game.CurrentAR.Storylet.Body);

            body += "</div>";

            if (result != null)
            {
                foreach(var inv in result.InventoryOps)
                {
                    body += RenderInventoryOp(inv);
                }
            }

            List<KeyValuePair<string, Storylet.Link>> specialLinks = new List<KeyValuePair<string, Storylet.Link>>();

            foreach (var kvp in game.CurrentAR.Options)
            {
                if (string.IsNullOrEmpty(kvp.Value.Special))
                {
                    body += RenderLink(kvp.Value, kvp.Key, game.Items);
                }
                else
                {
                    specialLinks.Add(kvp);
                }
            }

            foreach (var link in game.CurrentAR.NonOptions)
            {
                body += RenderLink(link, null, game.Items);
            }

            foreach (var kvp in specialLinks)
            {
                body += RenderLink(kvp.Value, kvp.Key, game.Items);
            }

            return body;
        }
예제 #17
0
        /// <summary>
        /// Generates documentation.
        /// </summary>
        public Model.GenerationError[] Generate()
        {
            // Initialize the list containing all generation errors
            List<Model.GenerationError> generationError = new List<Model.GenerationError>();

            // Ensute output directory exists
            if (!this.OutputDirectory.Exists)
            {
                this.OutputDirectory.Create();
            }

            // Read configuration
            ConfigurationLoader configurationLoader = new ConfigurationLoader();
            Configuration configuration;
            try
            {
                configuration = configurationLoader.Load(this.ConfigFile);
            }
            catch (System.Exception exception)
            {
                generationError.Add(new Model.GenerationError(this.ConfigFile.FullName, string.Format("Error during loading configuration: {0}", exception.Message)));
                return generationError.ToArray();
            }

            // Process all pages
            List<Model.Page> pages = new List<Model.Page>();
            foreach (Page page in configuration.Pages)
            {
                // Compute the page id used as a tab id and page prefix for bookmarking
                string pageId = page.Path.Replace(".", string.Empty).Replace("/", string.Empty);

                // Load the document
                Block document;
                FileInfo fileInfo = new FileInfo(page.Path);

                // Skip the page if doesn't exist
                if (!fileInfo.Exists)
                {
                    generationError.Add(new Model.GenerationError(this.ConfigFile.FullName, string.Format("Error during loading configuration: Could not find file '{0}'", fileInfo.FullName)));
                    continue;
                }

                // Process the page
                using (StreamReader reader = new StreamReader(new FileStream(new FileInfo(page.Path).FullName, FileMode.Open)))
                {
                    document = CommonMarkConverter.ProcessStage1(reader);
                }

                // Process snippet
                CommonMarkConverter.ProcessStage2(document);
                foreach (var node in document.AsEnumerable())
                {
                    // Filter fenced code
                    if (node.Block != null && node.Block.Tag == BlockTag.FencedCode)
                    {
                        // Buil extraction rule
                        string fencedCode = node.Block.FencedCodeData.Info;
                        SnippetExtractionRule snippetExtractionRule = SnippetExtractionRule.Parse(fencedCode);

                        // Extract and inject snippet and the factory were able to create an extractor
                        if (null != snippetExtractionRule)
                        {
                            // Cleanup Projbook specific syntax
                            node.Block.FencedCodeData.Info = snippetExtractionRule.Language;

                            // Inject snippet
                            try
                            {
                                // Retrieve the extractor instance
                                ISnippetExtractor snippetExtractor;
                                if (!this.extractorCache.TryGetValue(snippetExtractionRule.FileName, out snippetExtractor))
                                {
                                    snippetExtractor = this.snippetExtractorFactory.CreateExtractor(snippetExtractionRule);
                                    this.extractorCache[snippetExtractionRule.FileName] = snippetExtractor;
                                }

                                // Extract the snippet
                                Model.Snippet snippet = snippetExtractor.Extract(snippetExtractionRule.FileName, snippetExtractionRule.Pattern);
                                StringContent code = new StringContent();
                                code.Append(snippet.Content, 0, snippet.Content.Length);
                                node.Block.StringContent = code;
                            }
                            catch (SnippetExtractionException snippetExtraction)
                            {
                                generationError.Add(new Model.GenerationError(
                                    sourceFile: page.Path,
                                    message: string.Format("{0}: {1}", snippetExtraction.Message, snippetExtraction.Pattern)));
                            }
                            catch (System.Exception exception)
                            {
                                generationError.Add(new Model.GenerationError(
                                    sourceFile: page.Path,
                                    message: exception.Message));
                            }
                        }
                    }
                }

                // Setup custom formatter
                CommonMarkSettings.Default.OutputDelegate = (d, o, s) => new InjectAnchorHtmlFormatter(pageId, this.sectionSplittingIdentifier, o, s).WriteDocument(d);

                // Write to output
                MemoryStream documentStream = new MemoryStream();
                using (StreamWriter writer = new StreamWriter(documentStream))
                {
                    CommonMarkConverter.ProcessStage3(document, writer);
                }

                // Initialize the pre section content
                string preSectionContent = string.Empty;

                // Retrieve page content
                string pageContent = System.Text.Encoding.UTF8.GetString(documentStream.ToArray());

                // Build section list
                List<Model.Section> sections = new List<Model.Section>();
                Match match = regex.Match(pageContent);
                bool matched = false;
                while(match.Success)
                {
                    // Initialize the pre section part from 0 to the first matching index for the first matching
                    if (!matched)
                    {
                        preSectionContent = pageContent.Substring(0, match.Groups[0].Index);
                    }

                    // Create a new section and add to the known list
                    sections.Add(new Model.Section(
                        id: match.Groups[2].Value,
                        title: match.Groups[1].Value,
                        content: match.Groups[3].Value));

                    // Mode to the next match
                    match = match.NextMatch();
                    matched = true;
                }

                // If nothing has been matching simple consider the whole input as pre section content
                if (!matched)
                {
                    preSectionContent = pageContent;
                }

                // Add new page
                pages.Add(new Model.Page(
                    id: pageId,
                    title: page.Title,
                    preSectionContent: preSectionContent,
                    sections: sections.ToArray()));
            }

            // Standard generation
            try
            {
                this.GenerateFile(this.TemplateFile.FullName, this.TemplateFile.FullName, configuration, pages);
            }
            catch (System.Exception exception)
            {
                generationError.Add(new Model.GenerationError(this.TemplateFile.FullName, string.Format("Error during HTML generation: {0}", exception.Message)));
            }

            // Pdf specific generation
            string pdfTemplate = this.TemplateFilePdf.Exists ? this.TemplateFilePdf.FullName : this.TemplateFile.FullName;
            try
            {
                this.GenerateFile(pdfTemplate, this.TemplateFilePdf.FullName, configuration, pages);
            }
            catch (System.Exception exception)
            {
                generationError.Add(new Model.GenerationError(pdfTemplate, string.Format("Error during PDF generation: {0}", exception.Message)));
            }

            // Return the generation errors
            return generationError.ToArray();
        }
예제 #18
0
        public IEnumerable<StaticPageBuilderResponse> Convert(StaticPageConverterRequest request)
        {
            if (request == null) throw new ArgumentNullException("request");
            Contract.EndContractBlock();

            DirectoryInfo requestSourceRoot;
            IEnumerable<FileInfo> sourceFiles;

            var requestSourceFile = new FileInfo(request.Source);
            if (requestSourceFile.Exists)
            {
                requestSourceRoot = requestSourceFile.Directory;
                sourceFiles = new[] { requestSourceFile };
            }
            else
            {
                requestSourceRoot = new DirectoryInfo(request.Source);
                if (requestSourceRoot.Exists)
                {
                    var directories = request.Recursive
                        ? SearchAllDirectories(requestSourceRoot)
                        : new[] { requestSourceRoot };
                    sourceFiles = directories.SelectMany(d => d.EnumerateFiles("*.md"));
                }
                else
                {
                    sourceFiles = Enumerable.Empty<FileInfo>();
                }
            }

            var templateFile = requestSourceRoot.EnumerateFiles("_template.cshtml").FirstOrDefault();
            string razorTemplateCacheKey = null;
            if (templateFile != null && templateFile.Exists)
            {
                razorTemplateCacheKey = templateFile.FullName;
                Razor.Compile(File.ReadAllText(templateFile.FullName), typeof(TemplateModel), razorTemplateCacheKey);
            }

            CommonMarkSettings settings = null;
            var sourceRootUri = new Uri(requestSourceRoot.FullName + Path.DirectorySeparatorChar);
            var results = new List<StaticPageBuilderResponse>();
            foreach (var sourceFile in sourceFiles)
            {
                var localFileUri = new Uri(sourceFile.FullName);
                var relativeSourceFilePath = sourceRootUri.MakeRelative(localFileUri);
                if (Path.DirectorySeparatorChar != '/')
                {
                    relativeSourceFilePath = relativeSourceFilePath.Replace('/', Path.DirectorySeparatorChar);
                }

                var relativeTargetFilePath = Path.ChangeExtension(relativeSourceFilePath, "html");
                var targetFile = new FileInfo(Path.Combine(request.RelativeDestination, relativeTargetFilePath));

                CommonMark.Syntax.Block parsedDocument;
                using (var sourceStream = File.Open(sourceFile.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                using (var reader = new StreamReader(sourceStream))
                {
                    parsedDocument = CommonMarkConverter.ProcessStage1(reader, settings);
                }

                CommonMarkConverter.ProcessStage2(parsedDocument, settings);

                if (!targetFile.Directory.Exists)
                {
                    targetFile.Directory.Create();
                }

                using (var targetStream = File.Open(targetFile.FullName, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
                using (var writer = new StreamWriter(targetStream))
                {
                    if (razorTemplateCacheKey != null)
                    {
                        var markdownText = new StringBuilder();
                        using (var markdownWriter = new StringWriter(markdownText))
                        {
                            CommonMarkConverter.ProcessStage3(parsedDocument, markdownWriter, settings);
                        }
                        var htmlResultText = Razor.Run(razorTemplateCacheKey, new TemplateModel{
                            ContentHtml = markdownText.ToString()
                        });
                        writer.Write(htmlResultText);
                    }
                    else
                    {
                        CommonMarkConverter.ProcessStage3(parsedDocument, writer, settings);
                    }
                }

                results.Add(new StaticPageBuilderResponse
                {
                    ResultFile = targetFile
                });
            }

            return results;
        }
예제 #19
0
        /// <summary>
        /// Generates all documents.
        /// </summary>
        /// <returns>The generation errors.</returns>
        public GenerationError[] GenerateAll()
        {
            // Register bundles if pdf generation is not skipped
            if (!this.SkipPdf)
                this.RegisterHtmlToXLibraries();

            // Run generation for each configuration
            List<GenerationError> errors = new List<GenerationError>();
            foreach (Configuration configuration in this.IndexConfiguration.Configurations)
            {
                // Generate the documentation
                errors.AddRange(this.Generate(configuration));
            }

            // Generate the index html file if any index template is set
            if (!string.IsNullOrWhiteSpace(this.IndexConfiguration.Template))
            {
                errors.AddRange(this.GenerateIndex(this.IndexConfiguration));
            }

            // Report processing successful
            return errors.ToArray();
        }
예제 #20
0
        /// <summary>
        /// Create the template output
        /// </summary>
        public virtual string TransformText()
        {
            this.Write("\r\n");
            this.Write("\r\n\"");
            
            #line 16 "D:\Github\SharpDox.Plugins.Html\src\SharpDox.Plugins.Html\Templates\Repository\TypeData.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(TargetFx.Name));
            
            #line default
            #line hidden
            this.Write("\": { \r\n\t\t");
            
            #line 17 "D:\Github\SharpDox.Plugins.Html\src\SharpDox.Plugins.Html\Templates\Repository\TypeData.tt"

		var properties = new List<string>();
		properties.Add($"\"name\": \"{Type.Name}\"");
		properties.Add($"\"namespace\": \"{Type.Namespace.Fullname}\"");
		properties.Add($"\"syntax\": \"{Type.Syntax}\"");
		properties.Add($"\"linkedSyntax\": \"{Type.SyntaxTemplate.Transform(Helper.TransformLinkToken).ToObjectString()}\"");

		if(!Type.IsClassDiagramEmpty()) { 
			var height = Type.GetClassDiagram().GetSvgSize().Height;
			height = height > 300 ? 375 : height + 75;

			properties.Add($"\"classDiagram\": \"{Type.GetClassDiagram().ToSvg().Transform(Helper.TransformLinkToken).ToObjectString()}\"");
			properties.Add($"\"classDiagramHeight\": \"{height}\"");
			properties.Add($"\"fit\": \"{height == 375}\"");
		}
		if(Type.BaseTypes.Count > 0) {
			var baseTypes = string.Join(",", Type.BaseTypes.Select(baseType => 
				string.Format("{{\"id\": \"{0}\",\"name\": \"{1}\"}}", baseType.Type.Identifier, baseType.Type.Fullname)));

			properties.Add($"\"baseTypes\": [ {baseTypes} ]");
		} 
		if(Type.ImplementedInterfaces.Count > 0) {
			var implements = string.Join(",", Type.ImplementedInterfaces.Select(implementedInterface => 
				string.Format("{{\"id\": \"{0}\",\"name\": \"{1}\"}}", implementedInterface.Type.Identifier, implementedInterface.Type.Fullname)));

			properties.Add($"\"implements\": [ {implements} ]");
		}

		if(Type.Regions.Count > 0 && StepInput.HtmlConfig.ShowCode){
			var allRegions = new List<string>();
			foreach(var region in Type.Regions){
				allRegions.Add($"{{\"start\": \"{region.StartLine}\", \"end\": \"{region.EndLine}\", \"filepath\": \"{region.FilePath.ToObjectString()}\", \"filename\": \"{region.Filename.ToObjectString()}\", \"content\": \"{region.Content.ToObjectString().Replace("\t", "    ")}\"}}");
			}
			properties.Add($"\"regions\": [{string.Join(",", allRegions)}]");
		}		

		var documentation = Type.Documentations.GetElementOrDefault(StepInput.CurrentLanguage);
		if(documentation != null){
			var documentationTemplate = new DocumentationData { Documentation = documentation };
			var documentationText = documentationTemplate.TransformText();
			if(!string.IsNullOrWhiteSpace(documentationText)) properties.Add(documentationText);
		}
		
		if(Type.Fields.Count > 0) {
			properties.Add(string.Format("\"fields\": [{0}]", string.Join(",", Type.Fields.Select(sdField => new MemberData { Member = sdField, MemberType = "field", Repository = Repository }.TransformText()))));
		} 
		if(Type.Constructors.Count > 0) {
			properties.Add(string.Format("\"constructors\": [{0}]", string.Join(",", Type.Constructors.Select(sdContructor => new MemberData { Member = sdContructor, MemberType = "method", Repository = Repository }.TransformText()))));
		}
		if(Type.Methods.Count > 0) {
			properties.Add(string.Format("\"methods\": [{0}]", string.Join(",", Type.Methods.Select(sdMethod => new MemberData { Member = sdMethod, MemberType = "method", Repository = Repository }.TransformText()))));
		}
		if(Type.Events.Count > 0) {
			properties.Add(string.Format("\"events\": [{0}]", string.Join(",", Type.Events.Select(sdEvent => new MemberData { Member = sdEvent, MemberType = "event", Repository = Repository }.TransformText()))));
		}
		if(Type.Properties.Count > 0){
			properties.Add(string.Format("\"properties\": [{0}]", string.Join(",", Type.Properties.Select(sdProperty => new MemberData { Member = sdProperty, MemberType = "property", Repository = Repository }.TransformText()))));	
		} 
            
            #line default
            #line hidden
            this.Write("\r\n\t\t");
            
            #line 76 "D:\Github\SharpDox.Plugins.Html\src\SharpDox.Plugins.Html\Templates\Repository\TypeData.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(string.Join(",", properties)));
            
            #line default
            #line hidden
            this.Write("\t\r\n\t}\r\n\r\n");
            return this.GenerationEnvironment.ToString();
        }
예제 #21
0
        /// <summary>
        /// Extracts source directories from the csproj file.
        /// The expected directory info list is the csproj's directory and all project references.
        /// </summary>
        /// <param name="csprojFile"></param>
        /// <returns></returns>
        private DirectoryInfoBase[] ExtractSourceDirectories(FileInfoBase csprojFile)
        {
            // Data validation
            Ensure.That(() => csprojFile).IsNotNull();
            Ensure.That(csprojFile.Exists, string.Format("Could not find '{0}' file", csprojFile)).IsTrue();

            // Initialize the extracted directories
            List<DirectoryInfoBase> extractedSourceDirectories = new List<DirectoryInfoBase>();

            // Add the csproj's directory
            DirectoryInfoBase projectDirectory = this.fileSystem.DirectoryInfo.FromDirectoryName(this.fileSystem.Path.GetDirectoryName(csprojFile.FullName));
            extractedSourceDirectories.Add(projectDirectory);

            // Load xml document
            XmlDocument xmlDocument = new XmlDocument();
            using (Stream stream = csprojFile.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                xmlDocument.Load(stream);
            }

            // Extract
            XmlNamespaceManager xmlNamespaceManager = new XmlNamespaceManager(xmlDocument.NameTable);
            xmlNamespaceManager.AddNamespace("msbuild", "http://schemas.microsoft.com/developer/msbuild/2003");
            XmlNodeList xmlNodes = xmlDocument.SelectNodes("//msbuild:ProjectReference", xmlNamespaceManager);
            for (int i = 0; i < xmlNodes.Count; ++i)
            {
                XmlNode xmlNode = xmlNodes.Item(i);
                string includeValue = xmlNode.Attributes["Include"].Value;
                string combinedPath = this.fileSystem.Path.Combine(projectDirectory.FullName, includeValue);

                // The combinedPath can contains both forward and backslash path chunk.
                // In linux environment we can end up having "/..\" in the path which make the GetDirectoryName method bugging (returns empty).
                // For this reason we need to make sure that the combined path uses forward slashes
                combinedPath = combinedPath.Replace(@"\", "/");

                // Add the combined path
                extractedSourceDirectories.Add(this.fileSystem.DirectoryInfo.FromDirectoryName(this.fileSystem.Path.GetDirectoryName(this.fileSystem.Path.GetFullPath(combinedPath))));
            }

            // Return the extracted directories
            return extractedSourceDirectories.ToArray();
        }
 public WebServiceGateway()
 {
     sseEventBuffer = new List<SseEvent>();
 }
예제 #23
0
 public static List<string> ParseExtensionChangelog(List<string> changelog)
 {
     var lines = new List<string>
     {
         "<h1>Changelog</h1>",
         "<div id='changelog'>",
         CommonMarkConverter.Convert(string.Join("\n", changelog)),
         "</div>"
     };
     return lines;
 }
예제 #24
0
        static int Main(string[] args)
        {
            try
            {
                var argc = args.Length;
                int i;
                bool ast = false;
                List<string> files = new List<string>();
                string target = null;

                for (i = 0; i < argc; i++)
                {
                    if (string.Equals(args[i], "--version", StringComparison.OrdinalIgnoreCase))
                    {
                        Console.WriteLine("CommonMark.NET {0}", Document.AssemblyVersion);
                        Console.WriteLine(" - (c) 2014 Kārlis Gaņģis");
                        return 0;
                    }
                    else if ((string.Equals(args[i], "--help", StringComparison.OrdinalIgnoreCase)) ||
                             (string.Equals(args[i], "-h", StringComparison.OrdinalIgnoreCase)))
                    {
                        print_usage();
                        return 0;
                    }
                    else if (string.Equals(args[i], "--ast", StringComparison.OrdinalIgnoreCase))
                    {
                        ast = true;
                    }
                    else if (string.Equals(args[i], "--out", StringComparison.OrdinalIgnoreCase))
                    {
                        if (i == argc - 1 || args[i + 1].StartsWith("-"))
                        {
                            print_usage();
                            return 1;
                        }

                        i++;
                        target = args[i];
                    }
                    else if (args[i].StartsWith("-"))
                    {
                        print_usage();
                        return 1;
                    }
                    else
                    {
                        // treat as file argument
                        files.Add(args[i]);
                    }
                }

                OutputFormat format = ast ? OutputFormat.SyntaxTree : OutputFormat.Html;

                System.IO.TextWriter writer = target == null ? Console.Out : new System.IO.StreamWriter(target);

                try
                {
                    if (files.Count == 0)
                    {
                        // read from stdin
                        if (!Console.IsInputRedirected)
                        {
                            Console.WriteLine("Only redirected STDIN is supported.");
                            print_usage();
                            return 2;
                        }
                        Document.Load(Console.In).Export(writer, format);
                    }
                    else
                    {
                        // iterate over input file pointers
                        for (var g = 0; g < files.Count; g++)
                        {
                            using (var reader = new System.IO.StreamReader(files[g]))
                            {
                                Document.Load(reader).Export(writer, format);
                            }
                        }
                    }
                }
                finally
                {
                    if (writer != Console.Out)
                        writer.Close();
                }

                return 0;
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex.ToString());
                return -1;
            }
        }
예제 #25
0
        /// <summary>
        /// Generates documentation.
        /// </summary>
        public Model.GenerationError[] Generate()
        {
            // Initialize the list containing all generation errors
            List<Model.GenerationError> generationError = new List<Model.GenerationError>();

            // Ensute output directory exists
            if (!this.OutputDirectory.Exists)
            {
                this.OutputDirectory.Create();
            }

            // Read configuration
            ConfigurationLoader configurationLoader = new ConfigurationLoader();
            Configuration configuration;
            try
            {
                configuration = configurationLoader.Load(this.ConfigFile);
            }
            catch (System.Exception exception)
            {
                generationError.Add(new Model.GenerationError(this.ConfigFile.FullName, string.Format("Error during loading configuration: {0}", exception.Message)));
                return generationError.ToArray();
            }

            // Process all pages
            List<Model.Page> pages = new List<Model.Page>();
            bool first = true;
            foreach (Page page in configuration.Pages)
            {
                // Declare formatter
                InjectAnchorHtmlFormatter formatter = null;

                // Load the document
                Block document;
                FileInfo fileInfo = new FileInfo(page.Path);

                // Skip the page if doesn't exist
                if (!fileInfo.Exists)
                {
                    generationError.Add(new Model.GenerationError(this.ConfigFile.FullName, string.Format("Error during loading configuration: Could not find file '{0}'", fileInfo.FullName)));
                    continue;
                }

                // Process the page
                using (StreamReader reader = new StreamReader(new FileStream(new FileInfo(page.Path).FullName, FileMode.Open)))
                {
                    document = CommonMarkConverter.ProcessStage1(reader);
                }

                // Process snippet
                CommonMarkConverter.ProcessStage2(document);
                foreach (var node in document.AsEnumerable())
                {
                    // Filter fenced code
                    if (node.Block != null && node.Block.Tag == BlockTag.FencedCode)
                    {
                        // Extract snippet
                        string fencedCode = node.Block.FencedCodeData.Info;
                        ISnippetExtractor snippetExtractor = this.snippetExtractorFactory.CreateExtractor(fencedCode);

                        // Extract and inject snippet and the factory were able to create an extractor
                        if (null != snippetExtractor)
                        {
                            // Cleanup Projbook specific syntax
                            node.Block.FencedCodeData.Info = snippetExtractor.Language;

                            // Inject snippet
                            try
                            {
                                Model.Snippet snippet = snippetExtractor.Extract();
                                StringContent code = new StringContent();
                                code.Append(snippet.Content, 0, snippet.Content.Length);
                                node.Block.StringContent = code;
                            }
                            catch (SnippetExtractionException snippetExtraction)
                            {
                                generationError.Add(new Model.GenerationError(
                                    sourceFile: page.Path,
                                    message: string.Format("{0}: {1}", snippetExtraction.Message, snippetExtraction.Pattern)));
                            }
                            catch (System.Exception exception)
                            {
                                generationError.Add(new Model.GenerationError(
                                    sourceFile: page.Path,
                                    message: exception.Message));
                            }
                        }
                    }
                }

                // Setup custom formatter
                CommonMarkSettings.Default.OutputDelegate =
                    (d, output, settings) =>
                    {
                        formatter = new InjectAnchorHtmlFormatter(page.Path, output, settings);
                        formatter.WriteDocument(d);
                    };

                // Write to output
                MemoryStream documentStream = new MemoryStream();
                using (StreamWriter writer = new StreamWriter(documentStream))
                {
                    CommonMarkConverter.ProcessStage3(document, writer);
                }

                // Add new page
                pages.Add(new Model.Page(
                    id: page.Path.Replace(".", string.Empty).Replace("/", string.Empty),
                    title: page.Title,
                    isHome: first,
                    anchor: formatter.Anchors,
                    content: System.Text.Encoding.UTF8.GetString(documentStream.ToArray())));
                first = false;
            }

            // Standard generation
            try
            {
                this.GenerateFile(this.TemplateFile.FullName, this.TemplateFile.FullName, configuration, pages);
            }
            catch (System.Exception exception)
            {
                generationError.Add(new Model.GenerationError(this.TemplateFile.FullName, string.Format("Error during HTML generation: {0}", exception.Message)));
            }

            // Pdf specific generation
            string pdfTemplate = this.TemplateFilePdf.Exists ? this.TemplateFilePdf.FullName : this.TemplateFile.FullName;
            try
            {
                this.GenerateFile(pdfTemplate, this.TemplateFilePdf.FullName, configuration, pages);
            }
            catch (System.Exception exception)
            {
                generationError.Add(new Model.GenerationError(pdfTemplate, string.Format("Error during PDF generation: {0}", exception.Message)));
            }

            // Return the generation errors
            return generationError.ToArray();
        }
예제 #26
0
 /// <summary>
 /// Generates a file.
 /// </summary>
 /// <param name="templateName">The template name use as input.</param>
 /// <param name="targetName">The target name used as output.</param>
 /// <param name="configuration">The configuration to inject.</param>
 /// <param name="pages">The pages to inject.</param>
 private void GenerateFile(string templateName, string targetName, Configuration configuration, List<Model.Page> pages)
 {
     // Generate final documentation from the template using razor engine
     string fileName = string.Format("{0}-generated{1}", Path.GetFileNameWithoutExtension(targetName), Path.GetExtension(targetName));
     string outputFileHtml = Path.Combine(this.OutputDirectory.FullName, fileName);
     using (var reader = new StreamReader(new FileStream(templateName, FileMode.Open)))
     using (var writer = new StreamWriter(new FileStream(outputFileHtml, FileMode.Create)))
     {
         var config = new TemplateServiceConfiguration();
         config.Language = Language.CSharp;
         config.EncodedStringFactory = new RawStringFactory();
         var service = RazorEngineService.Create(config);
         Engine.Razor = service;
         string processed = Engine.Razor.RunCompile(new LoadedTemplateSource(reader.ReadToEnd()), string.Empty, null, new { Title = configuration.Title, Pages = pages });
         writer.WriteLine(processed);
     }
 }
예제 #27
0
        static int Main(string[] args)
        {
            var sources = new List<System.IO.TextReader>();
            var benchmark = false;
            var benchmarkIterations = 20;
            var target = Console.Out;
            var runPerlTests = false;
            var settings = CommonMarkSettings.Default.Clone();

            try
            {
                for (var i = 0; i < args.Length; i++)
                {
                    if (string.Equals(args[i], "--version", StringComparison.OrdinalIgnoreCase))
                    {
                        Console.WriteLine("CommonMark.NET {0}", CommonMarkConverter.Version);
                        Console.WriteLine(" - (c) 2014-2015 Kārlis Gaņģis");
                        return 0;
                    }
                    else if ((string.Equals(args[i], "--help", StringComparison.OrdinalIgnoreCase)) ||
                             (string.Equals(args[i], "-h", StringComparison.OrdinalIgnoreCase)))
                    {
                        PrintUsage();
                        return 0;
                    }
                    else if (string.Equals(args[i], "--perltest", StringComparison.OrdinalIgnoreCase))
                    {
                        runPerlTests = true;
                    }
                    else if (string.Equals(args[i], "--ast", StringComparison.OrdinalIgnoreCase))
                    {
                        settings.OutputFormat = OutputFormat.SyntaxTree;
                    }
                    else if (string.Equals(args[i], "--sourcepos", StringComparison.OrdinalIgnoreCase))
                    {
                        settings.TrackSourcePosition = true;
                    }
                    else if (string.Equals(args[i], "--bench", StringComparison.OrdinalIgnoreCase))
                    {
                        benchmark = true;
                        if (i != args.Length - 1)
                        {
                            if (!int.TryParse(args[i + 1], System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture, out benchmarkIterations))
                                benchmarkIterations = 20;
                            else
                                i++;
                        }
                    }
                    else if (string.Equals(args[i], "--out", StringComparison.OrdinalIgnoreCase))
                    {
                        if (i == args.Length - 1 || args[i + 1].StartsWith("-"))
                        {
                            PrintUsage();
                            return 1;
                        }

                        i++;
                        target = new System.IO.StreamWriter(args[i]);
                    }
                    else if (args[i].StartsWith("-"))
                    {
                        PrintUsage(args[i]);
                        return 1;
                    }
                    else
                    {
                        // treat as file argument
                        sources.Add(new System.IO.StreamReader(args[i]));
                    }
                }

                if (sources.Count == 0)
                {
                    if (runPerlTests)
                    {
                        Console.InputEncoding = Encoding.UTF8;
                        Console.OutputEncoding = Encoding.UTF8;

                        // runtests.pl writes directly to STDIN but will not send Ctrl+C and also
                        // will get confused by the additional information written to STDOUT
                        var sb = new StringBuilder();
                        while (Console.In.Peek() != -1)
                            sb.AppendLine(Console.In.ReadLine());

                        sources.Add(new System.IO.StringReader(sb.ToString()));
                    }
                    else if (!Console.IsInputRedirected)
                    {
                        Console.InputEncoding = Encoding.Unicode;
                        Console.OutputEncoding = Encoding.Unicode;

                        Console.WriteLine("Enter the source. Press Enter after the last line and" + Environment.NewLine + "then press Ctrl+C to run parser.");
                        Console.WriteLine();

                        Console.CancelKeyPress += (s, a) =>
                        {
                            a.Cancel = true;
                            Console.WriteLine("Output:");
                            Console.WriteLine();
                        };

                        sources.Add(Console.In);
                    }
                    else
                    {
                        Console.InputEncoding = Encoding.UTF8;
                        Console.OutputEncoding = Encoding.UTF8;

                        sources.Add(Console.In);
                    }
                }

                if (benchmark)
                {
                    Console.WriteLine("Running the benchmark...");
                    foreach (var source in sources)
                    {
                        // by using a in-memory source, the disparity of results is reduced.
                        var data = source.ReadToEnd();
                        
                        // in-memory source that gets reused further reduces the disparity.
                        var builder = new StringBuilder(2 * 1024 * 1024);

                        var sw = new System.Diagnostics.Stopwatch();
                        var mem = GC.GetTotalMemory(true);
                        long mem2 = 0;

                        for (var x = -1 - benchmarkIterations / 10; x < benchmarkIterations; x++)
                        {
                            if (x == 0)
                                sw.Start();

                            builder.Length = 0;
                            using (var reader = new System.IO.StringReader(data))
                            using (var twriter = new System.IO.StringWriter(builder))
                                CommonMarkConverter.Convert(reader, twriter, settings);

                            if (mem2 == 0)
                                mem2 = GC.GetTotalMemory(false);

                            GC.Collect();
                        }

                        sw.Stop();
                        target.WriteLine("Time spent: {0:0.#}ms    Approximate memory usage: {1:0.000}MB",
                            (decimal)sw.ElapsedMilliseconds / benchmarkIterations,
                            (mem2 - mem) / 1024M / 1024M);
                    }
                }
                else
                {
                    foreach (var source in sources)
                        CommonMarkConverter.Convert(source, target, settings);
                }

                if (System.Diagnostics.Debugger.IsAttached)
                {
                    Console.WriteLine("Press any key to continue...");
                    Console.ReadKey(true);
                }

                return 0;
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex.ToString());
                return -1;
            }
            finally
            {
                foreach (var s in sources)
                    if (s != Console.In)
                        s.Close();

                if (target != Console.Out)
                    target.Close();
            }
        }
        private void ExecuteRefreshCommandInternal()
        {
            DocumentationHtmlContent = null;

            IUttBaseScriptItem scriptItem = (ProjectService.CurrentProject as VuGenProject)?.Script;

            var actionFilePaths = new List<string>();

            Factotum.ProcessRecursively(
                scriptItem,
                item =>
                    //// ReSharper disable once RedundantEnumerableCastCall - False detection
                    (item as IUttCollectionScriptItem<IUttBaseScriptItem>)?.ScriptItems
                        ?? (item as IUttCollectionScriptItem<IActionScriptItem>)?.ScriptItems
                            .Cast<IUttBaseScriptItem>(),
                item =>
                {
                    var actionScriptItem = item as IActionScriptItem;
                    if (actionScriptItem != null)
                    {
                        actionFilePaths.Add(actionScriptItem.FullFileName);
                    }
                });

            var parsedFiles = Parser.ParseFiles(actionFilePaths);

            var content = parsedFiles
                .SelectMany(obj => obj.Elements)
                .OfType<ParsedComment>()
                .Select(obj => obj.Content)
                .Join(Environment.NewLine + Environment.NewLine);

            var settings = CommonMarkSettings.Default.Clone();
            settings.AdditionalFeatures = CommonMarkAdditionalFeatures.All;
            settings.RenderSoftLineBreaksAsLineBreaks = true;

            var document = CommonMarkConverter.Parse(content, settings);

            ////var htmlContent = CommonMarkConverter.Convert(content, settings);
            ////Trace.WriteLine(htmlContent);

            using (var stringWriter = new StringWriter())
            {
                var formatter = new HtmlFormatter(stringWriter, settings);
                formatter.WriteDocument(document);

                DocumentationHtmlContent = stringWriter.ToString();
            }
        }