public string Render(SourceFile sourceFile, string template, object data) { var pipeline = new MarkdownPipelineBuilder() .UseAdvancedExtensions() .Build(); var result = Markdown.ToHtml(template, pipeline); return result.Trim(); }
public Browser(string file) { var builder = new MarkdownPipelineBuilder() .UsePragmaLines() .UseAdvancedExtensions(); _pipeline = builder.Build(); _zoomFactor = GetZoomFactor(); _file = file; _htmlTemplate = GetHtmlTemplate(); _currentViewLine = -1; InitBrowser(); }
public override MarkdownPipeline GetPipeline() { var pipelineBuilder = new MarkdownPipelineBuilder(); if (PipeTables) pipelineBuilder = pipelineBuilder.UsePipeTables(); if (GridTables) pipelineBuilder = pipelineBuilder.UseGridTables(); if (ExtraEmphasis) pipelineBuilder = pipelineBuilder.UseEmphasisExtras(); if (DefinitionLists) pipelineBuilder = pipelineBuilder.UseDefinitionLists(); if (Footnotes) pipelineBuilder = pipelineBuilder.UseFootnotes(); if (TaskLists) pipelineBuilder = pipelineBuilder.UseTaskLists(); if (ExtraBulletLists) pipelineBuilder = pipelineBuilder.UseListExtras(); if (Abbreviations) pipelineBuilder = pipelineBuilder.UseAbbreviations(); if (Emoji) pipelineBuilder = pipelineBuilder.UseEmojiAndSmiley(); return pipelineBuilder.Build(); }
public void CodeSampleWorks() { var codebase = Assembly.GetExecutingAssembly().GetName().CodeBase; var directory = Path.GetDirectoryName(codebase); if (directory == null) { throw new NullReferenceException("appPath came back null."); } var appPath = new Uri(directory).LocalPath; var folder = Path.Combine(appPath, "Example"); var inputMarkdown = Path.Combine(folder, "README.md"); var referenceFile = Path.Combine(folder, "expected.html"); var expectedHtml = File.ReadAllText(referenceFile); var markdown = File.ReadAllText(inputMarkdown); var pipeline = new MarkdownPipelineBuilder() .UseAdvancedExtensions() .UseSyntaxHighlighting() .Build(); var html = Markdown.ToHtml(markdown, pipeline); var actualHtml = File.ReadAllText(Path.Combine(folder, "_template.html")) .Replace("{{{this}}}", html); actualHtml = actualHtml.Replace("\r\n", "\n").Replace("\n", "\r\n"); File.WriteAllText(Path.Combine(folder, "actual.html"), actualHtml); Assert.Equal(expectedHtml, actualHtml); }
public void Setup(MarkdownPipelineBuilder pipeline) { _pipeline = pipeline; _pipeline.DocumentProcessed += PipelineOnDocumentProcessed; }
public static MarkdownPipelineBuilder UseQuoteSectionNote(this MarkdownPipelineBuilder pipeline, MarkdownContext context) { pipeline.Extensions.Insert(0, new QuoteSectionNoteExtension(context)); return(pipeline); }
public static string ToPlainText(this JournalPost post) { var pipeline = new MarkdownPipelineBuilder().Build(); return(Markdown.ToPlainText(post.Content, pipeline)); }
/// <summary> /// Adds a new <see cref="SyntaxHighlighterMarkdownExtension"/> to the specified Markdig <paramref name="pipeline"/>. /// </summary> /// <param name="pipeline">The pipeline.</param> /// <returns>The pipeline.</returns> public static MarkdownPipelineBuilder UseSyntaxHighlighter(this MarkdownPipelineBuilder pipeline) { pipeline.Extensions.Add(new SyntaxHighlighterMarkdownExtension()); return(pipeline); }
public void Setup(MarkdownPipelineBuilder pipeline) { pipeline.BlockParsers.AddIfNotAlready <CodeSnippetParser>(); }
public void Setup(MarkdownPipelineBuilder pipeline) => pipeline.BlockParsers.Insert(0, new BlockParser());
public static MarkdownPipelineBuilder UseYamlHeader(this MarkdownPipelineBuilder pipeline) { pipeline.Extensions.Insert(0, new YamlHeaderExtension()); return(pipeline); }
public void Setup(MarkdownPipelineBuilder pipeline) { pipeline.InlineParsers.AddIfNotAlready <VariableInlineParser>(); }
public static MarkdownPipelineBuilder UseMonikerRange(this MarkdownPipelineBuilder pipeline, MarkdownContext context) { pipeline.Extensions.AddIfNotAlready(new MonikerRangeExtension(context)); return(pipeline); }
public static MarkdownPipelineBuilder UseHeadingIdRewriter(this MarkdownPipelineBuilder pipeline) { pipeline.Extensions.Add(new HeadingIdExtension()); return(pipeline); }
public static MarkdownPipelineBuilder UseTabGroup(this MarkdownPipelineBuilder pipeline, MarkdownContext context) { pipeline.Extensions.Add(new TabGroupExtension(context)); return(pipeline); }
/// <summary> /// This extension removes all the block parser except paragragh. Please use this extension in the last. /// </summary> public static MarkdownPipelineBuilder UseInlineOnly(this MarkdownPipelineBuilder pipeline) { pipeline.Extensions.Add(new InlineOnlyExtentsion()); return(pipeline); }
public static MarkdownPipelineBuilder UseNestedColumn(this MarkdownPipelineBuilder pipeline, MarkdownContext context) { pipeline.Extensions.AddIfNotAlready(new NestedColumnExtension(context)); return(pipeline); }
public static MarkdownPipelineBuilder UseMonikerRange(this MarkdownPipelineBuilder pipeline) { pipeline.Extensions.AddIfNotAlready <MonikerRangeExtension>(); return(pipeline); }
public static MarkdownPipelineBuilder UseLineNumber(this MarkdownPipelineBuilder pipeline, Func <object, string> getFilePath = null) { pipeline.Extensions.Add(new LineNumberExtension(getFilePath)); return(pipeline); }
public static MarkdownPipelineBuilder RemoveUnusedExtensions(this MarkdownPipelineBuilder pipeline) { pipeline.Extensions.RemoveAll(extension => extension is CustomContainerExtension); return(pipeline); }
public static MarkdownPipelineBuilder UseIncludeFile(this MarkdownPipelineBuilder pipeline, MarkdownContext context) { pipeline.Extensions.Insert(0, new InclusionExtension(context)); return(pipeline); }
/// <summary> /// Constructs a DocComment instance from the documentation comments /// associated with a source code element. /// </summary> /// <param name="docComments">The doc comments from the source code</param> /// <param name="name">The name of the element</param> /// <param name="deprecated">Flag indicating whether or not the element had a Deprecated attribute</param> /// <param name="replacement">The name of the replacement element for deprecated elements, if given</param> public DocComment(IEnumerable <string> docComments, string name, bool deprecated, string replacement) { string GetHeadingText(HeadingBlock heading) { var sb = new StringBuilder(); foreach (var item in heading.Inline) { sb.Append(item.ToString()); } return(sb.ToString()); } string GetParagraphText(LeafBlock leaf) { var sb = new StringBuilder(); foreach (var item in leaf.Inline) { sb.Append(item.ToString()); } return(sb.ToString()); } string ToMarkdown(IEnumerable <Block> blocks) { var writer = new StringWriter(); var renderer = new NormalizeRenderer(writer); var pipeline = new MarkdownPipelineBuilder().Build(); pipeline.Setup(renderer); foreach (var block in blocks) { renderer.Render(block); } // We convert \n to \r because the YAML serialization will eventually // output \n\n for \n, but \r\n for \r. return(writer.ToString().TrimEnd().Replace('\n', '\r')); } List <ValueTuple <string, List <Block> > > BreakIntoSections(IEnumerable <Block> blocks, int level) { var key = ""; var accum = new List <Block>(); var result = new List <ValueTuple <string, List <Block> > >(); foreach (var block in blocks) { if (block is HeadingBlock heading) { if (heading.Level == level) { if (accum.Count > 0) { result.Add(new ValueTuple <string, List <Block> >(key, accum)); accum = new List <Block>(); } key = GetHeadingText(heading); } else { accum.Add(block); } } else { accum.Add(block); } } if (accum.Count > 0) { result.Add(new ValueTuple <string, List <Block> >(key, accum)); } return(result); } void ParseListSection(IEnumerable <Block> blocks, List <string> accum, bool lowerCase) { foreach (var block in blocks) { if (block is ListBlock list) { foreach (var sub in block.Descendants()) { if (sub is ListItemBlock item) { // Some special treatment for funky doc comments in some of the Canon if (item.Count == 1 && item.LastChild is LeafBlock leaf && leaf.Inline != null && leaf.Inline.FirstChild is LiteralInline literal) { var itemText = lowerCase ? GetParagraphText(leaf).ToLowerInvariant() : GetParagraphText(leaf); if (itemText.StartsWith("@\"") && itemText.EndsWith("\"")) { itemText = itemText.Substring(2, itemText.Length - 3); } literal.Content = new Markdig.Helpers.StringSlice(itemText.ToLowerInvariant()); } accum.Add(ToMarkdown(new Block[] { item })); } } } } } void ParseMapSection(IEnumerable <Block> blocks, Dictionary <string, string> accum) { var subsections = BreakIntoSections(blocks, 2); foreach ((var key, var subs) in subsections) { // TODO: when we add the ability to flag warnings from the doc comment builder, // we should check here for duplicate keys and generate a warning if appropriate. accum[key] = ToMarkdown(subs); } } // First element is not matching, second is matching (List <Block>, List <Block>) PartitionNestedSection(IEnumerable <Block> blocks, int level, string name) { var inMatch = false; var result = (new List <Block>(), new List <Block>()); foreach (var block in blocks) { var skip = false; if ((block is HeadingBlock heading) && (heading.Level == level)) { inMatch = GetHeadingText(heading).Equals(name); skip = true; } if (inMatch) { if (!skip) { result.Item2.Add(block); } } else { result.Item1.Add(block); } } return(result); } // Initialize to safe empty values this.Summary = ""; this.Description = ""; this.ShortSummary = ""; this.Documentation = ""; this.Input = new Dictionary <string, string>(); this.Output = ""; this.TypeParameters = new Dictionary <string, string>(); this.Example = ""; this.Remarks = ""; this.SeeAlso = new List <string>(); this.References = ""; var deprecationSummary = String.IsNullOrWhiteSpace(replacement) ? DiagnosticItem.Message(WarningCode.DeprecationWithoutRedirect, new string[] { name }) : DiagnosticItem.Message(WarningCode.DeprecationWithRedirect, new string[] { name, "@\"" + replacement.ToLowerInvariant() + "\"" }); var deprecationDetails = ""; var text = String.Join("\n", docComments); // Only parse if there are comments to parse if (!string.IsNullOrWhiteSpace(text)) { var doc = Markdown.Parse(text); var sections = BreakIntoSections(doc, 1); List <Block> summarySection = new List <Block>(); List <Block> descriptionSection = new List <Block>(); foreach ((var tag, var section) in sections) { switch (tag) { case "Summary": this.Summary = ToMarkdown(section); summarySection.AddRange(section); // For now, the short hover information gets the first paragraph of the summary. this.ShortSummary = ToMarkdown(section.GetRange(0, 1)); break; case "Deprecated": if (String.IsNullOrWhiteSpace(name)) { deprecationSummary = ToMarkdown(section.GetRange(0, 1)); if (section.Count > 1) { deprecationDetails = ToMarkdown(section.GetRange(1, section.Count - 1)); } } else { deprecationDetails = ToMarkdown(section); } deprecated = true; break; case "Description": this.Description = ToMarkdown(section); descriptionSection = section; break; case "Input": ParseMapSection(section, this.Input); break; case "Output": this.Output = ToMarkdown(section); break; case "Type Parameters": ParseMapSection(section, this.TypeParameters); break; case "Example": this.Example = ToMarkdown(section); break; case "Remarks": (var remarks, var examples) = PartitionNestedSection(section, 2, "Example"); if ((examples.Count > 0) && (this.Example == "")) { this.Example = ToMarkdown(examples); } this.Remarks = ToMarkdown(remarks); break; case "See Also": // seeAlso is a list of UIDs, which are all lower case, // so pass true to lowercase all strings found in this section ParseListSection(section, this.SeeAlso, true); break; case "References": this.References = ToMarkdown(section); break; default: // TODO: add diagnostic warning about unknown tag break; } } this.Documentation = ToMarkdown(summarySection.Concat(descriptionSection)); } if (deprecated) { var shortDeprecationText = DeprecatedWarning + "\r" + deprecationSummary; var longDeprecationText = shortDeprecationText + (String.IsNullOrWhiteSpace(deprecationDetails) ? "" : "\r") + deprecationDetails; this.Summary += "\r" + longDeprecationText; this.ShortSummary = shortDeprecationText; this.Documentation = deprecationSummary; } }
public void WriteTo(TextWriter writer, HtmlEncoder encoder) { var pipeline = new MarkdownPipelineBuilder().DisableHtml().Build(); Markdig.Markdown.ToHtml(_markdown, writer, pipeline); }
public static void VerifyMarkup( string markdown, string html, string[] errors = null, string[] dependencies = null, bool lineNumber = false, string filePath = "test.md", Dictionary <string, string> tokens = null, Dictionary <string, string> files = null, Action <MarkdownObject> verifyAST = null) { errors = errors ?? Array.Empty <string>(); tokens = tokens ?? new Dictionary <string, string>(); files = files ?? new Dictionary <string, string>(); var actualErrors = new List <string>(); var actualDependencies = new HashSet <string>(); var markdownContext = new MarkdownContext( getToken: key => tokens.TryGetValue(key, out var value) ? value : null, logInfo: (a, b, c, d) => { }, logSuggestion: Log("suggestion"), logWarning: Log("warning"), logError: Log("error"), readFile: ReadFile); var pipelineBuilder = new MarkdownPipelineBuilder() .UseDocfxExtensions(markdownContext) .UseYamlFrontMatter(); if (lineNumber) { pipelineBuilder.UseLineNumber(); } var pipeline = pipelineBuilder.Build(); using (InclusionContext.PushFile(filePath)) { var actualHtml = Markdown.ToHtml(markdown, pipeline); if (html != null) { Assert.Equal( html.Replace("\r", "").Replace("\n", ""), actualHtml.Replace("\r", "").Replace("\n", "")); } Assert.Equal(errors.OrderBy(_ => _), actualErrors.OrderBy(_ => _)); if (dependencies != null) { Assert.Equal(dependencies.OrderBy(_ => _), actualDependencies.OrderBy(_ => _)); } } MarkdownContext.LogActionDelegate Log(string level) { return((code, message, origin, line) => actualErrors.Add(code)); } (string content, object file) ReadFile(string path, object relativeTo, MarkdownObject origin) { var key = Path.Combine(Path.GetDirectoryName(relativeTo.ToString()), path).Replace('\\', '/'); if (path.StartsWith("~/")) { path = path.Substring(2); key = path; } actualDependencies.Add(path); return(files.TryGetValue(key, out var value) ? (value, key) : default);
/// <summary> /// 使用Markdig扩展。 /// </summary> /// <typeparam name="TExtension">扩展类型。</typeparam> /// <param name="builder">当前管道构建实例。</param> /// <returns>返回管道构建实例。</returns> public static MarkdownPipelineBuilder Use <TExtension>(this MarkdownPipelineBuilder builder) where TExtension : IMarkdownExtension, new() { return(builder.Use(new TExtension())); }
public void Setup(MarkdownPipelineBuilder pipeline) { pipeline.BlockParsers.Find <ListBlockParser>()?.ItemParsers.AddIfNotAlready <CheckboxParser>(); }
public void Setup(MarkdownPipelineBuilder pipeline) { pipeline.InlineParsers.AddIfNotAlready <BlogMetadataParser>(); }
public static (DescriptionYaml Meta, string Style, Dictionary <string, string> Descriptions) ParseDescription(string input) { var pipeline = new MarkdownPipelineBuilder() .UseYamlFrontMatter() .Build(); var document = Markdown.Parse(input, pipeline); var yamlBlock = document.Descendants <YamlFrontMatterBlock>().FirstOrDefault(); DescriptionYaml meta = null; if (yamlBlock != null) { var yaml = input.Substring(yamlBlock.Span.Start, yamlBlock.Span.Length).Trim('-'); meta = Deserializer.FromValueDeserializer(new DeserializerBuilder() .WithNamingConvention(CamelCaseNamingConvention.Instance).BuildValueDeserializer()) .Deserialize <DescriptionYaml>(yaml); } var isAfterEnHeading = false; var isStyleBlock = false; var isCodeBlock = false; var zhPart = ""; var enPart = ""; var stylePart = ""; var codePart = ""; for (var i = yamlBlock?.Line ?? 0; i < document.Count; i++) { var block = document[i]; if (block is YamlFrontMatterBlock) { continue; } if (block is HeadingBlock heading && heading.Level == 2 && heading.Inline.FirstChild.ToString() == "en-US") { isAfterEnHeading = true; } if (block is CodeBlock codeBlock) { isCodeBlock = true; } if (block is HtmlBlock htmlBlock && htmlBlock.Type == HtmlBlockType.ScriptPreOrStyle) { isStyleBlock = true; } if (block is HeadingBlock h && h.Level == 2) { continue; } using var writer = new StringWriter(); var renderer = new HtmlRenderer(writer); var blockHtml = renderer.Render(block); if (!isAfterEnHeading) { zhPart += blockHtml; } else if (isStyleBlock) { stylePart += blockHtml; } //else if (isCodeBlock) //{ // codePart += blockHtml; //} else { enPart += blockHtml; } } stylePart = stylePart.Replace("<style>", "").Replace("</style>", ""); return(meta, stylePart, new Dictionary <string, string>() {
public void Setup(MarkdownPipelineBuilder pipeline) { // Make sure we don't have a delegate twice pipeline.DocumentProcessed -= PipelineOnDocumentProcessed; pipeline.DocumentProcessed += PipelineOnDocumentProcessed; }
/// <summary> /// Adds a new <see cref="SyntaxHighlighterMarkdownExtension"/> to the specified Markdig <paramref name="pipeline"/>. /// </summary> /// <param name="pipeline">The pipeline.</param> /// <param name="options">The options for configuration the syntax highlighter extension.</param> /// <returns>The pipeline.</returns> public static MarkdownPipelineBuilder UseSyntaxHighlighter(this MarkdownPipelineBuilder pipeline, out SyntaxHighlighterOptions options) { options = new SyntaxHighlighterOptions(); pipeline.Extensions.Add(new SyntaxHighlighterMarkdownExtension(options)); return(pipeline); }
public static MarkdownPipelineBuilder UseQuoteSectionNote(this MarkdownPipelineBuilder pipeline, MarkdownServiceParameters parameters) { pipeline.Extensions.Insert(0, new QuoteSectionNoteExtension(parameters)); return(pipeline); }
/// <summary> /// Setups this extension for the specified pipeline. /// </summary> /// <param name="pipeline">The pipeline.</param> public void Setup(MarkdownPipelineBuilder pipeline) { }
public static MarkdownPipelineBuilder UseCodeSnippet(this MarkdownPipelineBuilder pipeline, MarkdigCompositor compositor, MarkdownContext context) { pipeline.Extensions.Insert(0, new CodeSnippetExtension(compositor, context)); return(pipeline); }
public void Setup(MarkdownPipelineBuilder pipeline) {}
public static MarkdownPipelineBuilder UseXref(this MarkdownPipelineBuilder pipeline) { pipeline.Extensions.Insert(0, new XrefInlineExtension()); return(pipeline); }