/// <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(); }
/// <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(); }