public void TestGfmWithSequenceRewrite() { const string source = @" # A ## B ### C"; const string expected = @"<h2 id=""a"">A</h2> <h4 id=""b"">B</h4> <h4 id=""c"">C</h4> "; var builder = new GfmEngineBuilder(new Options()); builder.Rewriter = MarkdownTokenRewriterFactory.Sequence( MarkdownTokenRewriterFactory.FromLambda( (IMarkdownRewriteEngine e, MarkdownHeadingBlockToken t) => t.Depth <= 2 ? new MarkdownHeadingBlockToken(t.Rule, t.Context, t.Content, t.Id, t.Depth + 1, t.SourceInfo) : null), MarkdownTokenRewriterFactory.FromLambda( (IMarkdownRewriteEngine e, MarkdownHeadingBlockToken t) => t.Depth == 3 ? new MarkdownHeadingBlockToken(t.Rule, t.Context, t.Content, t.Id, t.Depth + 1, t.SourceInfo) : null) ); var engine = builder.CreateEngine(new HtmlRenderer()); var result = engine.Markup(source); Assert.Equal(expected.Replace("\r\n", "\n"), result); }
public void TestGfmWithValidator() { const string source = "#Hello World"; const string expected = "<h1 id=\"hello-world\">Hello World</h1>\n"; const string expectedMessage = "a space is expected after '#'"; string message = null; var builder = new GfmEngineBuilder(new Options { LegacyMode = true, }); builder.Rewriter = MarkdownTokenRewriterFactory.FromValidators( MarkdownTokenValidatorFactory.FromLambda( (MarkdownHeadingBlockToken token) => { if (!token.SourceInfo.Markdown.StartsWith("# ")) { message = expectedMessage; } })); var engine = builder.CreateEngine(new HtmlRenderer()); var result = engine.Markup(source); Assert.Equal(expected.Replace("\r\n", "\n"), result); Assert.Equal(expectedMessage, message); }
public IMarkdownTokenRewriter Create() { var list = new List <IMarkdownTokenValidator>(); foreach (var contract in ValidatorContracts) { foreach (IMarkdownTokenValidatorProvider vp in CompositionHost.GetExports(typeof(IMarkdownTokenValidatorProvider), contract)) { list.AddRange(vp.GetValidators()); } } var context = new MarkdownRewriterContext(CompositionHost, TagValidators); list.Add(MarkdownTokenValidatorFactory.FromLambda <MarkdownTagInlineToken>(context.Validate)); return(MarkdownTokenRewriterFactory.FromLambda( (IMarkdownRewriteEngine engine, IMarkdownToken token) => { using (new LoggerPhaseScope(MarkdownValidatePhaseName)) { foreach (var item in list) { item.Validate(token); } } return null; })); }
protected void CreateRewriters() { Rewriter = MarkdownTokenRewriterFactory.Composite( MarkdownTokenRewriterFactory.FromLambda( (IMarkdownRewriteEngine e, AzureNoteBlockToken t) => new DfmNoteBlockToken(t.Rule, t.Context, t.NoteType.Substring("AZURE.".Length), t.Content, t.SourceInfo) ), MarkdownTokenRewriterFactory.FromLambda( (IMarkdownRewriteEngine e, AzureBlockquoteBlockToken t) => new MarkdownBlockquoteBlockToken(t.Rule, t.Context, t.Tokens, t.SourceInfo) ), MarkdownTokenRewriterFactory.FromLambda( (IMarkdownRewriteEngine e, MarkdownLinkInlineToken t) => new MarkdownLinkInlineToken(t.Rule, t.Context, NormalizeAzureLink(t.Href, MarkdownExtension, t.Context, t.SourceInfo.Markdown), t.Title, t.Content, t.SourceInfo) ), MarkdownTokenRewriterFactory.FromLambda( (IMarkdownRewriteEngine e, AzureSelectorBlockToken t) => new DfmSectionBlockToken(t.Rule, t.Context, GenerateAzureSelectorAttributes(t.SelectorType, t.SelectorConditions), t.SourceInfo) ), MarkdownTokenRewriterFactory.FromLambda( (IMarkdownRewriteEngine e, AzureHtmlMetadataBlockToken t) => new DfmYamlHeaderBlockToken(t.Rule, t.Context, GenerateYamlHeaderContent(t.Properties, t.Tags), t.SourceInfo) ), MarkdownTokenRewriterFactory.FromLambda( (IMarkdownRewriteEngine e, AzureMigrationIncludeBlockToken t) => new DfmIncludeBlockToken(t.Rule, t.Context, t.Src, t.Name, t.Title, t.SourceInfo.Markdown, t.SourceInfo) ), MarkdownTokenRewriterFactory.FromLambda( (IMarkdownRewriteEngine e, AzureMigrationIncludeInlineToken t) => new DfmIncludeInlineToken(t.Rule, t.Context, t.Src, t.Name, t.Title, t.SourceInfo.Markdown, t.SourceInfo) ), MarkdownTokenRewriterFactory.FromLambda( (IMarkdownRewriteEngine e, AzureVideoBlockToken t) => new DfmVideoBlockToken(t.Rule, t.Context, GenerateAzureVideoLink(t.Context, t.VideoId, t.SourceInfo.Markdown), t.SourceInfo) ) ); }
public IMarkdownTokenRewriter CreateRewriter() { var context = new MarkdownRewriterContext(Container, GetEnabledTagRules().ToImmutableList()); return(new MarkdownTokenRewriteWithScope( MarkdownTokenRewriterFactory.FromValidators( MarkdownValidatePhaseName, GetEnabledRules().Concat( new[] { MarkdownTokenValidatorFactory.FromLambda <IMarkdownToken>(context.Validate) })), MarkdownValidatePhaseName)); }
public DfmEngine CreateDfmEngine(object renderer) { return(new DfmEngine( CreateParseContext().SetBaseFolder(_baseDir ?? string.Empty).SetFallbackFolders(_fallbackFolders), MarkdownTokenRewriterFactory.Composite( MarkdownTokenRewriterFactory.FromLambda(GetTabGroupIdRewriter()), Rewriter), renderer, Options) { TokenTreeValidator = TokenTreeValidator, TokenAggregators = TokenAggregators, }); }
protected void CreateRewriters() { Rewriter = MarkdownTokenRewriterFactory.Composite( MarkdownTokenRewriterFactory.FromLambda( (IMarkdownRewriteEngine e, AzureIncludeInlineToken t) => new DfmIncludeInlineToken(t.Rule, t.Context, t.Src, t.Name, t.Title, t.Raw, t.RawMarkdown) ), MarkdownTokenRewriterFactory.FromLambda( (IMarkdownRewriteEngine e, AzureIncludeBlockToken t) => new DfmIncludeBlockToken(t.Rule, t.Context, t.Src, t.Name, t.Title, t.Raw, t.RawMarkdown) ), MarkdownTokenRewriterFactory.FromLambda( (IMarkdownRewriteEngine e, AzureNoteBlockToken t) => new DfmNoteBlockToken(t.Rule, t.Context, t.NoteType.Substring("AZURE.".Length), t.Content, t.RawMarkdown) ), MarkdownTokenRewriterFactory.FromLambda( (IMarkdownRewriteEngine e, AzureBlockquoteBlockToken t) => new DfmBlockquoteBlockToken(t.Rule, t.Context, t.Tokens, t.RawMarkdown) ) ); }
protected void CreateRewriters() { Rewriter = MarkdownTokenRewriterFactory.Composite( MarkdownTokenRewriterFactory.FromLambda( (IMarkdownRewriteEngine e, AzureNoteBlockToken t) => new DfmNoteBlockToken(t.Rule, t.Context, t.NoteType.Substring("AZURE.".Length), t.Content, t.RawMarkdown) ), MarkdownTokenRewriterFactory.FromLambda( (IMarkdownRewriteEngine e, AzureBlockquoteBlockToken t) => new MarkdownBlockquoteBlockToken(t.Rule, t.Context, t.Tokens, t.RawMarkdown) ), MarkdownTokenRewriterFactory.FromLambda( (IMarkdownRewriteEngine e, MarkdownLinkInlineToken t) => new MarkdownLinkInlineToken(t.Rule, t.Context, AppendDefaultExtension(t.Href, MarkdownExtension), t.Title, t.Content, t.RawMarkdown) ), MarkdownTokenRewriterFactory.FromLambda( (IMarkdownRewriteEngine e, AzureSelectorBlockToken t) => new DfmSectionBlockToken(t.Rule, t.Context, GenerateAzureSelectorAttributes(t.SelectorType, t.SelectorConditions), t.RawMarkdown) ), MarkdownTokenRewriterFactory.FromLambda( (IMarkdownRewriteEngine e, AzureHtmlMetadataBlockToken t) => new DfmYamlHeaderBlockToken(t.Rule, t.Context, GenerateYamlHeaderContent(t.Properties, t.Tags), t.RawMarkdown) ) ); }
public void TestGfmWithValidatorWithQuery() { const string source = @"abc (not match) - abc (match) - a*b*c (match) - xyz - x > a**b**c (not match)"; const string expected = @"<p>abc (not match)</p> <ul> <li>abc (match)</li> <li>a<em>b</em>c (match)</li> <li>xyz</li> <li>x</li> </ul> <blockquote> <p>a<strong>b</strong>c (not match)</p> </blockquote> "; int matchCount = 0; var builder = new GfmEngineBuilder(new Options()); builder.Rewriter = MarkdownTokenRewriterFactory.FromValidators( MarkdownTokenValidatorFactory.FromLambda( (MarkdownListItemBlockToken token) => { var text = string.Concat(from t in token.Descendants <MarkdownTextToken>() select t.Content); if (text.Contains("abc")) { matchCount++; } })); var engine = builder.CreateEngine(new HtmlRenderer()); var result = engine.Markup(source); Assert.Equal(expected.Replace("\r\n", "\n"), result); Assert.Equal(2, matchCount); }
public void TestGfmWithValidatorWithContext() { const string source = @"# Title-1 # Title-2"; const string expected = @"<h1 id=""title-1"">Title-1</h1> <h1 id=""title-2"">Title-2</h1> "; const string expectedMessage = "expected one title in one document."; string message = null; var builder = new GfmEngineBuilder(new Options()); builder.Rewriter = MarkdownTokenRewriterFactory.FromValidators( MarkdownTokenValidatorFactory.FromLambda( (MarkdownHeadingBlockToken token) => { var re = MarkdownTokenValidatorContext.CurrentRewriteEngine; if (token.Depth == 1) { re.SetVariable("count", (int)re.GetVariable("count") + 1); } }, re => { re.SetVariable("count", 0); re.SetPostProcess("h1 count", re1 => { if ((int)re.GetVariable("count") != 1) { message = expectedMessage; } }); })); var engine = builder.CreateEngine(new HtmlRenderer()); var result = engine.Markup(source); Assert.Equal(expected.Replace("\r\n", "\n"), result); Assert.Equal(expectedMessage, message); }
private static ImmutableArray <IMarkdownToken> Tokenize(string markdown, string file) { var gfm = new GfmEngineBuilder(new Options()).CreateEngine(new HtmlRenderer()); var sourceInfo = SourceInfo.Create(markdown.Replace("\r\n", "\n"), file); var tokens = gfm.Parser.Tokenize(sourceInfo); tokens = TokenHelper.CreateParagraghs( gfm.Parser, MarkdownParagraphBlockRule.Instance, tokens, true, sourceInfo); var rewriter = new MarkdownRewriteEngine( gfm, MarkdownTokenRewriterFactory.FromLambda <IMarkdownRewriteEngine, TwoPhaseBlockToken>( (e, t) => t.Extract(gfm.Parser))); tokens = rewriter.Rewrite(tokens); return(tokens); }
public void ParseWithBadRewrite() { const string source = @" # Heading "; var builder = new GfmEngineBuilder(new Options()); builder.Rewriter = MarkdownTokenRewriterFactory.Loop( MarkdownTokenRewriterFactory.Composite( MarkdownTokenRewriterFactory.FromLambda( (IMarkdownRewriteEngine e, MarkdownHeadingBlockToken t) => new MarkdownTextToken(t.Rule, t.Context, t.RawMarkdown, t.RawMarkdown) ), MarkdownTokenRewriterFactory.FromLambda( (IMarkdownRewriteEngine e, MarkdownTextToken t) => new MarkdownHeadingBlockToken(t.Rule, t.Context, new InlineContent(ImmutableArray <IMarkdownToken> .Empty), "aaaa", 1, t.RawMarkdown) ) ), 10); var engine = builder.CreateEngine(new HtmlRenderer()); Assert.Throws <InvalidOperationException>(() => engine.Markup(source)); }
public void TestSourceInfo_Table() { const string File = "test.md"; var gfm = new GfmEngineBuilder(new Options()).CreateEngine(new HtmlRenderer()); var tokens = gfm.Parser.Tokenize( SourceInfo.Create(@" | H1 | H2 | |----|----| |R1C1|R1C2| |R2C1|R2C2| ".Replace("\r\n", "\n"), File)); var rewriter = new MarkdownRewriteEngine( gfm, MarkdownTokenRewriterFactory.FromLambda <IMarkdownRewriteEngine, TwoPhaseBlockToken>( (e, t) => t.Extract(gfm.Parser))); tokens = rewriter.Rewrite(tokens); Assert.Equal(2, tokens.Length); Assert.IsType <MarkdownTableBlockToken>(tokens[1]); var table = (MarkdownTableBlockToken)tokens[1]; Assert.Equal(2, table.Header.Length); Assert.Equal(2, table.Cells.Length); Assert.Equal(2, table.SourceInfo.LineNumber); Assert.Equal(File, table.SourceInfo.File); Assert.Equal(2, table.Header[0].SourceInfo.LineNumber); Assert.Equal(2, table.Header[1].SourceInfo.LineNumber); Assert.Equal(4, table.Cells[0][0].SourceInfo.LineNumber); Assert.Equal(4, table.Cells[0][1].SourceInfo.LineNumber); Assert.Equal(5, table.Cells[1][0].SourceInfo.LineNumber); Assert.Equal(5, table.Cells[1][1].SourceInfo.LineNumber); }
public void TestGfmWithRewrite() { const string source = @" Heading ======= Sub-heading ----------- ### Another deeper heading Paragraphs are separated by a blank line. Leave 2 spaces at the end of a line to do a line break Text attributes *italic*, **bold**, `monospace`, ~~strikethrough~~ . A [link](http://example.com). Shopping list: * apples * oranges * pears Numbered list: 1. apples 2. oranges 3. pears "; const string expected = @"<p>Paragraphs are separated by a blank line.</p> <p>Leave 2 spaces at the end of a line to do a<br>line break</p> <p>Text attributes <em>italic</em>, <strong>bold</strong>, <code>monospace</code>, <del>strikethrough</del> .</p> <p>A <a href=""http://example.com"">link</a>.</p> <p>Shopping list:</p> <ul> <li>apples</li> <li>oranges</li> <li>pears</li> </ul> <p>Numbered list:</p> <ol> <li>apples</li> <li>oranges</li> <li>pears</li> </ol> "; var builder = new GfmEngineBuilder(new Options()); builder.Rewriter = MarkdownTokenRewriterFactory.FromLambda( (IMarkdownRewriteEngine e, MarkdownHeadingBlockToken t) => new MarkdownIgnoreToken(t.Rule, t.Context, t.RawMarkdown) // ignore all heading ); var engine = builder.CreateEngine(new HtmlRenderer()); var result = engine.Markup(source); Assert.Equal(expected.Replace("\r\n", "\n"), result); }
public void TestSourceInfo_BlockquoteAndList() { const string File = "test.md"; var gfm = new GfmEngineBuilder(new Options()).CreateEngine(new HtmlRenderer()); var tokens = gfm.Parser.Tokenize( SourceInfo.Create(@"> blockquote > [link text](sometarget) > > - list item 1 > - list item 1-1 > - list item 1-2 > - list item 2 > > more para. ".Replace("\r\n", "\n"), File)); var rewriter = new MarkdownRewriteEngine( gfm, MarkdownTokenRewriterFactory.FromLambda <IMarkdownRewriteEngine, TwoPhaseBlockToken>( (e, t) => t.Extract(gfm.Parser))); tokens = rewriter.Rewrite(tokens); Assert.Equal(1, tokens.Length); Assert.IsType <MarkdownBlockquoteBlockToken>(tokens[0]); var blockquote = (MarkdownBlockquoteBlockToken)tokens[0]; Assert.Equal(3, blockquote.Tokens.Length); Assert.Equal(1, blockquote.SourceInfo.LineNumber); Assert.Equal(File, blockquote.SourceInfo.File); Assert.IsType <MarkdownParagraphBlockToken>(blockquote.Tokens[0]); { var para = (MarkdownParagraphBlockToken)blockquote.Tokens[0]; Assert.Equal(1, para.SourceInfo.LineNumber); Assert.Equal(File, para.SourceInfo.File); Assert.Equal(2, para.InlineTokens.Tokens.Length); Assert.IsType <MarkdownTextToken>(para.InlineTokens.Tokens[0]); var text = (MarkdownTextToken)para.InlineTokens.Tokens[0]; Assert.Equal(1, text.SourceInfo.LineNumber); Assert.Equal(File, text.SourceInfo.File); Assert.IsType <MarkdownLinkInlineToken>(para.InlineTokens.Tokens[1]); var link = (MarkdownLinkInlineToken)para.InlineTokens.Tokens[1]; Assert.Equal(2, link.SourceInfo.LineNumber); Assert.Equal(File, link.SourceInfo.File); } Assert.IsType <MarkdownListBlockToken>(blockquote.Tokens[1]); { var list = (MarkdownListBlockToken)blockquote.Tokens[1]; Assert.Equal(4, list.SourceInfo.LineNumber); Assert.Equal(File, list.SourceInfo.File); Assert.Equal(2, list.Tokens.Length); Assert.IsType <MarkdownListItemBlockToken>(list.Tokens[0]); { var listItem = (MarkdownListItemBlockToken)list.Tokens[0]; Assert.Equal(4, listItem.SourceInfo.LineNumber); Assert.Equal(File, listItem.SourceInfo.File); Assert.IsType <MarkdownNonParagraphBlockToken>(listItem.Tokens[0]); var np = (MarkdownNonParagraphBlockToken)listItem.Tokens[0]; Assert.Equal(1, np.Content.Tokens.Length); Assert.Equal(4, np.SourceInfo.LineNumber); Assert.Equal(File, np.SourceInfo.File); Assert.IsType <MarkdownListBlockToken>(listItem.Tokens[1]); var subList = (MarkdownListBlockToken)listItem.Tokens[1]; Assert.Equal(2, subList.Tokens.Length); Assert.IsType <MarkdownListItemBlockToken>(subList.Tokens[0]); { var subListItem = (MarkdownListItemBlockToken)subList.Tokens[0]; Assert.Equal(5, subListItem.SourceInfo.LineNumber); Assert.Equal(File, subListItem.SourceInfo.File); } Assert.IsType <MarkdownListItemBlockToken>(subList.Tokens[1]); { var subListItem = (MarkdownListItemBlockToken)subList.Tokens[1]; Assert.Equal(6, subListItem.SourceInfo.LineNumber); Assert.Equal(File, subListItem.SourceInfo.File); } } Assert.IsType <MarkdownListItemBlockToken>(list.Tokens[1]); { var listItem = (MarkdownListItemBlockToken)list.Tokens[1]; Assert.Equal(7, listItem.SourceInfo.LineNumber); Assert.Equal(File, listItem.SourceInfo.File); } } Assert.IsType <MarkdownParagraphBlockToken>(blockquote.Tokens[2]); { var para = (MarkdownParagraphBlockToken)blockquote.Tokens[2]; Assert.Equal(9, para.SourceInfo.LineNumber); Assert.Equal(File, para.SourceInfo.File); } }
public void TestSourceInfo_Basic() { const string File = "test.md"; var gfm = new GfmEngineBuilder(new Options()).CreateEngine(new HtmlRenderer()); var tokens = gfm.Parser.Tokenize( SourceInfo.Create(@" # HEAD1 First line. More line. ## HEAD2 Yeah!".Replace("\r\n", "\n"), File)); var rewriter = new MarkdownRewriteEngine( gfm, MarkdownTokenRewriterFactory.FromLambda <IMarkdownRewriteEngine, TwoPhaseBlockToken>( (e, t) => t.Extract(gfm.Parser))); tokens = rewriter.Rewrite(tokens); Assert.Equal(5, tokens.Length); Assert.IsType <MarkdownNewLineBlockToken>(tokens[0]); Assert.IsType <MarkdownHeadingBlockToken>(tokens[1]); Assert.IsType <MarkdownParagraphBlockToken>(tokens[2]); Assert.IsType <MarkdownHeadingBlockToken>(tokens[3]); Assert.IsType <MarkdownParagraphBlockToken>(tokens[4]); var para = (MarkdownParagraphBlockToken)tokens[2]; Assert.Equal(3, para.InlineTokens.Tokens.Length); Assert.IsType <MarkdownTextToken>(para.InlineTokens.Tokens[0]); Assert.IsType <MarkdownBrInlineToken>(para.InlineTokens.Tokens[1]); Assert.IsType <MarkdownTextToken>(para.InlineTokens.Tokens[2]); Assert.Equal(1, tokens[0].SourceInfo.LineNumber); Assert.Equal(File, tokens[0].SourceInfo.File); Assert.Equal("\n\n", tokens[0].SourceInfo.Markdown); Assert.Equal(3, tokens[1].SourceInfo.LineNumber); Assert.Equal(File, tokens[1].SourceInfo.File); Assert.Equal("# HEAD1\n", tokens[1].SourceInfo.Markdown); Assert.Equal(4, tokens[2].SourceInfo.LineNumber); Assert.Equal(File, tokens[2].SourceInfo.File); Assert.Equal("First line. \nMore line.\n", tokens[2].SourceInfo.Markdown); Assert.Equal(4, para.InlineTokens.Tokens[0].SourceInfo.LineNumber); Assert.Equal(File, para.InlineTokens.Tokens[0].SourceInfo.File); Assert.Equal("First line.", para.InlineTokens.Tokens[0].SourceInfo.Markdown); Assert.Equal(4, para.InlineTokens.Tokens[1].SourceInfo.LineNumber); Assert.Equal(File, para.InlineTokens.Tokens[1].SourceInfo.File); Assert.Equal(" \n", para.InlineTokens.Tokens[1].SourceInfo.Markdown); Assert.Equal(5, para.InlineTokens.Tokens[2].SourceInfo.LineNumber); Assert.Equal(File, para.InlineTokens.Tokens[2].SourceInfo.File); Assert.Equal("More line.", para.InlineTokens.Tokens[2].SourceInfo.Markdown); Assert.Equal(6, tokens[3].SourceInfo.LineNumber); Assert.Equal(File, tokens[3].SourceInfo.File); Assert.Equal("## HEAD2\n", tokens[3].SourceInfo.Markdown); Assert.Equal(7, tokens[4].SourceInfo.LineNumber); Assert.Equal(File, tokens[4].SourceInfo.File); Assert.Equal("Yeah!", tokens[4].SourceInfo.Markdown); }
public IMarkdownTokenRewriter Create() { var context = new MarkdownRewriterContext(CompositionHost, Validators); return(MarkdownTokenRewriterFactory.FromLambda <IMarkdownRewriteEngine, MarkdownTagInlineToken>(context.Validate)); }
public void TestGfmWithValidatorWithParents() { const string source = @"# abc > *abc* - abc abc "; const string expected = @"<h1 id=""abc"">abc</h1> <blockquote> <p><em>abc</em></p> </blockquote> <ul> <li>abc</li> </ul> <p>abc</p> "; int headingTextCount = 0; int blockquoteTextCount = 0; int listTextCount = 0; int paraTextCount = 0; var builder = new GfmEngineBuilder(new Options()); builder.Rewriter = MarkdownTokenRewriterFactory.FromValidators( MarkdownTokenValidatorFactory.FromLambda( (MarkdownTextToken token) => { if (token.Content == "abc") { var re = MarkdownTokenValidatorContext.CurrentRewriteEngine; foreach (var parent in re.GetParents()) { if (parent is MarkdownHeadingBlockToken) { headingTextCount++; } else if (parent is MarkdownBlockquoteBlockToken) { blockquoteTextCount++; } else if (parent is MarkdownListItemBlockToken) { listTextCount++; } else if (parent is MarkdownParagraphBlockToken) { paraTextCount++; } } } })); var engine = builder.CreateEngine(new HtmlRenderer()); var result = engine.Markup(source); Assert.Equal(expected.Replace("\r\n", "\n"), result); Assert.Equal(1, headingTextCount); Assert.Equal(1, blockquoteTextCount); Assert.Equal(1, listTextCount); Assert.Equal(2, paraTextCount); }