public void TestInclusion_InlineLevel()
        {
            // 1. Prepare data
            var root = @"
Inline [!include[ref1](ref1.md ""This is root"")]
Inline [!include[ref3](ref3.md ""This is root"")]
";

            var ref1 = @"[!include[ref2](ref2.md ""This is root"")]";
            var ref2 = @"## Inline inclusion do not parse header [!include[root](root.md ""This is root"")]";
            var ref3 = @"**Hello**";

            File.WriteAllText("root.md", root);
            File.WriteAllText("ref1.md", ref1);
            File.WriteAllText("ref2.md", ref2);
            File.WriteAllText("ref3.md", ref3);

            var marked = DocfxFlavoredMarked.Markup(root, "root.md");

            Assert.Equal("<p>Inline <!-- BEGIN INCLUDE: Include content from &quot;ref1.md&quot; --><!-- BEGIN INCLUDE: Include content from &quot;ref2.md&quot; -->## Inline inclusion do not parse header <!-- BEGIN ERROR INCLUDE: Unable to resolve [!include[root](root.md &quot;This is root&quot;)]: Circular dependency found in &quot;ref2.md&quot; -->[!include[root](root.md \"This is root\")]<!--END ERROR INCLUDE --><!--END INCLUDE --><!--END INCLUDE -->\nInline <!-- BEGIN INCLUDE: Include content from &quot;ref3.md&quot; --><strong>Hello</strong><!--END INCLUDE --></p>\n", marked);
        }
Exemple #2
0
        public void CodeSnippetTagsShouldMatchCaseInsensitive()
        {
            //arange
            var content = @"// <tag1>
line1
// <tag2>
line2
// </tag2>
line3
// </TAG1>
// <unmatched>
";

            File.WriteAllText("Program.cs", content.Replace("\r\n", "\n"));

            // act
            var marked = DocfxFlavoredMarked.Markup("[!code[tag1](Program.cs#Tag1)]", "Program.cs");

            // assert
            var expected = "<pre><code name=\"tag1\">line1\nline2\nline3\n</code></pre>";

            Assert.Equal(expected.Replace("\r\n", "\n"), marked);
        }
Exemple #3
0
        public void TestRendererCreator()
        {
            var p        = new TestDfmRendererPartProvider();
            var renderer = CustomizedRendererCreator.CreateRenderer(
                new DfmRenderer(),
                new[] { p },
                null);
            var engine = DocfxFlavoredMarked
                         .CreateBuilder(".")
                         .CreateDfmEngine(renderer);
            var result = engine.Markup(@"```cs
public void TestRendererCreator()
```
```cs-x
public void TestRendererCreator()
```", "a.md");

            Assert.Equal(@"<pre><code class=""lang-cs"">public void TestRendererCreator()
</code></pre><pre class=""x""><code class=""lang-cs"">public void TestRendererCreator()
</code></pre>".Replace("\r\n", "\n"), result);
            (renderer as IDisposable).Dispose();
            Assert.True(p.CodeRendererPartInstance.Disposed);
        }
Exemple #4
0
            public DfmService(
                DfmServiceProvider provider,
                string baseDir,
                string templateDir,
                ICompositionContainer container,
                ImmutableDictionary <string, string> tokens,
                IReadOnlyList <string> fallbackFolders,
                IReadOnlyDictionary <string, object> parameters)
            {
                var options = DocfxFlavoredMarked.CreateDefaultOptions();

                options.LegacyMode             = provider.LegacyMode;
                options.ShouldFixId            = provider.ShouldFixId;
                options.ShouldExportSourceInfo = true;
                options.XHtml = true;
                Builder       = new DfmEngineBuilder(
                    options,
                    baseDir,
                    templateDir,
                    fallbackFolders,
                    container)
                {
                    TokenTreeValidator = MarkdownTokenTreeValidatorFactory.Combine(provider.TokenTreeValidator)
                };
                _tokens  = tokens;
                Renderer = CustomizedRendererCreator.CreateRenderer(
                    new DfmRenderer {
                    Tokens = _tokens
                },
                    provider.DfmRendererPartProviders,
                    parameters);
                foreach (var c in provider.DfmEngineCustomizers)
                {
                    c.Customize(Builder, parameters);
                }
                _incrementalContextHash = ComputeIncrementalContextHash(baseDir, templateDir, provider.TokenTreeValidator, parameters);
            }
        public MarkdigMarkdownRenderer(Stack <IMarkdownToken> processedBlockTokens, string basePath, bool useLegacyMode = true, MigrationRule rule = MigrationRule.All)
        {
            var option = DocfxFlavoredMarked.CreateDefaultOptions();

            option.LegacyMode = useLegacyMode;
            var builder = new DfmEngineBuilder(option);
            var render  = new DfmRenderer();

            _dfmEngine     = builder.CreateDfmEngine(render);
            _dfmHtmlRender = new DfmHtmlRender(useLegacyMode);
            _rule          = rule;

            var parameter = new MarkdownServiceParameters
            {
                BasePath   = basePath,
                Extensions = new Dictionary <string, object>
                {
                    { "EnableSourceInfo", false }
                }
            };

            _service = new MarkdigMarkdownService(parameter);
            _processedBlockTokens = processedBlockTokens;
        }
Exemple #6
0
        public void TestDfmFencesBlockLevel()
        {
            var root = @"
[!code-FakeREST[REST](api.json)]
[!Code-FakeREST-i[REST-i](api.json ""This is root"")]
[!CODE[No Language](api.json)]
[!code-js[empty](api.json)]
";

            var apiJsonContent = @"
{
   ""method"": ""GET"",
   ""resourceFormat"": ""https://outlook.office.com/api/v1.0/me/events?$select=Subject,Organizer,Start,End"",
   ""requestUrl"": ""https://outlook.office.com/api/v1.0/me/events?$select=Subject,Organizer,Start,End"",
   ""requestHeaders"": {
                ""Accept"": ""application/json""
   }
}";

            File.WriteAllText("api.json", apiJsonContent.Replace("\r\n", "\n"));
            var marked = DocfxFlavoredMarked.Markup(root, "api.json");

            Assert.Equal("<pre><code class=\"lang-FakeREST\" name=\"REST\">\n{\n   &quot;method&quot;: &quot;GET&quot;,\n   &quot;resourceFormat&quot;: &quot;https://outlook.office.com/api/v1.0/me/events?$select=Subject,Organizer,Start,End&quot;,\n   &quot;requestUrl&quot;: &quot;https://outlook.office.com/api/v1.0/me/events?$select=Subject,Organizer,Start,End&quot;,\n   &quot;requestHeaders&quot;: {\n                &quot;Accept&quot;: &quot;application/json&quot;\n   }\n}\n</code></pre><pre><code class=\"lang-FakeREST-i\" name=\"REST-i\" title=\"This is root\">\n{\n   &quot;method&quot;: &quot;GET&quot;,\n   &quot;resourceFormat&quot;: &quot;https://outlook.office.com/api/v1.0/me/events?$select=Subject,Organizer,Start,End&quot;,\n   &quot;requestUrl&quot;: &quot;https://outlook.office.com/api/v1.0/me/events?$select=Subject,Organizer,Start,End&quot;,\n   &quot;requestHeaders&quot;: {\n                &quot;Accept&quot;: &quot;application/json&quot;\n   }\n}\n</code></pre><pre><code name=\"No Language\">\n{\n   &quot;method&quot;: &quot;GET&quot;,\n   &quot;resourceFormat&quot;: &quot;https://outlook.office.com/api/v1.0/me/events?$select=Subject,Organizer,Start,End&quot;,\n   &quot;requestUrl&quot;: &quot;https://outlook.office.com/api/v1.0/me/events?$select=Subject,Organizer,Start,End&quot;,\n   &quot;requestHeaders&quot;: {\n                &quot;Accept&quot;: &quot;application/json&quot;\n   }\n}\n</code></pre><pre><code class=\"lang-js\" name=\"empty\">\n{\n   &quot;method&quot;: &quot;GET&quot;,\n   &quot;resourceFormat&quot;: &quot;https://outlook.office.com/api/v1.0/me/events?$select=Subject,Organizer,Start,End&quot;,\n   &quot;requestUrl&quot;: &quot;https://outlook.office.com/api/v1.0/me/events?$select=Subject,Organizer,Start,End&quot;,\n   &quot;requestHeaders&quot;: {\n                &quot;Accept&quot;: &quot;application/json&quot;\n   }\n}\n</code></pre>", marked);
        }
Exemple #7
0
        public void TestSectionNoteInBlockQuote(string source, string expected)
        {
            var markedContent = DocfxFlavoredMarked.Markup(source);

            Assert.Equal(expected.Replace("\r\n", "\n"), markedContent);
        }
Exemple #8
0
        public void TestBlockLevelInclusionWithSameFile()
        {
            // -r
            //  |- r.md
            //  |- a
            //  |  |- a.md
            //  |- b
            //  |  |- token.md
            //  |- c
            //     |- d
            //        |- d.md
            //  |- img
            //  |  |- img.jpg
            var r     = @"
[!include[](a/a.md)]
[!include[](c/d/d.md)]
";
            var a     = @"
[!include[](../b/token.md)]";
            var token = @"
![](../img/img.jpg)
[](#anchor)
[a](../a/a.md)
[](invalid.md)
[d](../c/d/d.md#anchor)
";
            var d     = @"
[!include[](../../b/token.md)]";

            WriteToFile("r/r.md", r);
            WriteToFile("r/a/a.md", a);
            WriteToFile("r/b/token.md", token);
            WriteToFile("r/c/d/d.md", d);
            var dependency = new HashSet <string>();
            var marked     = DocfxFlavoredMarked.Markup(a, "r/a/a.md", dependency: dependency);
            var expected   = @"<!-- BEGIN INCLUDE: Include content from &quot;r/b/token.md&quot; --><p><img src=""~/r/img/img.jpg"" alt="""">
<a href=""#anchor""></a>
<a href=""~/r/a/a.md"">a</a>
<a href=""~/r/b/invalid.md""></a>
<a href=""~/r/c/d/d.md#anchor"">d</a></p>
<!--END INCLUDE -->".Replace("\r\n", "\n");

            Assert.Equal(expected, marked);
            Assert.Equal(
                new[] { "../b/token.md" },
                dependency.OrderBy(x => x));

            dependency.Clear();
            marked = DocfxFlavoredMarked.Markup(d, "r/c/d/d.md", dependency: dependency);
            Assert.Equal(expected, marked);
            Assert.Equal(
                new[] { "../../b/token.md" },
                dependency.OrderBy(x => x));

            dependency.Clear();
            marked = DocfxFlavoredMarked.Markup(r, "r/r.md", dependency: dependency);
            Assert.Equal($@"<!-- BEGIN INCLUDE: Include content from &quot;r/a/a.md&quot; -->{expected}<!--END INCLUDE --><!-- BEGIN INCLUDE: Include content from &quot;r/c/d/d.md&quot; -->{expected}<!--END INCLUDE -->", marked);
            Assert.Equal(
                new[] { "a/a.md", "b/token.md", "c/d/d.md" },
                dependency.OrderBy(x => x));
        }
Exemple #9
0
        public void TestFallback_InclusionWithCodeFences()
        {
            // -root_folder (this is also docset folder)
            //  |- root.md
            //  |- a_folder
            //     |- a.md
            //  |- code_folder
            //     |- sample1.cs
            // -fallback_folder
            //  |- a_folder
            //     |- code_in_a.cs
            //  |- code_folder
            //     |- sample2.cs

            // 1. Prepare data
            var root = @"markdown root.md main content start.

mardown a content in root.md content start

[!include[a](a_folder/a.md ""This is a.md"")]

mardown a content in root.md content end

sample 1 code in root.md content start

[!CODE-cs[this is sample 1 code](code_folder/sample1.cs)]

sample 1 code in root.md content end

sample 2 code in root.md content start

[!CODE-cs[this is sample 2 code](code_folder/sample2.cs)]

sample 2 code in root.md content end

markdown root.md main content end.";

            var a = @"markdown a.md main content start.

code_in_a code in a.md content start

[!CODE-cs[this is code_in_a code](code_in_a.cs)]

code_in_a in a.md content end

markdown a.md a.md content end.";

            var code_in_a = @"namespace code_in_a{}";

            var sample1 = @"namespace sample1{}";

            var sample2 = @"namespace sample2{}";

            var uniqueFolderName = Path.GetRandomFileName();

            WriteToFile($"{uniqueFolderName}/root_folder/root.md", root);
            WriteToFile($"{uniqueFolderName}/root_folder/a_folder/a.md", a);
            WriteToFile($"{uniqueFolderName}/root_folder/code_folder/sample1.cs", sample1);
            WriteToFile($"{uniqueFolderName}/fallback_folder/a_folder/code_in_a.cs", code_in_a);
            WriteToFile($"{uniqueFolderName}/fallback_folder/code_folder/sample2.cs", sample2);

            try
            {
                EnvironmentContext.SetBaseDirectory($"{uniqueFolderName}/root_folder");
                var fallbackFolders = new List <string> {
                    { Path.Combine(Directory.GetCurrentDirectory(), $"{uniqueFolderName}/fallback_folder") }
                };

                // Verify root.md markup result
                var rootDependency = new HashSet <string>();
                var rootMarked     = DocfxFlavoredMarked.Markup(Path.Combine(Directory.GetCurrentDirectory(), $"{uniqueFolderName}/root_folder"), root, fallbackFolders, "root.md", dependency: rootDependency);
                Assert.Equal(@"<p>markdown root.md main content start.</p>
<p>mardown a content in root.md content start</p>
<p>markdown a.md main content start.</p>
<p>code_in_a code in a.md content start</p>
<pre><code class=""lang-cs"" name=""this is code_in_a code"">namespace code_in_a{}
</code></pre><p>code_in_a in a.md content end</p>
<p>markdown a.md a.md content end.</p>
<p>mardown a content in root.md content end</p>
<p>sample 1 code in root.md content start</p>
<pre><code class=""lang-cs"" name=""this is sample 1 code"">namespace sample1{}
</code></pre><p>sample 1 code in root.md content end</p>
<p>sample 2 code in root.md content start</p>
<pre><code class=""lang-cs"" name=""this is sample 2 code"">namespace sample2{}
</code></pre><p>sample 2 code in root.md content end</p>
<p>markdown root.md main content end.</p>
".Replace("\r\n", "\n"), rootMarked);
                Assert.Equal(
                    new[] { "../fallback_folder/a_folder/code_in_a.cs", "../fallback_folder/code_folder/sample2.cs", "a_folder/a.md", "a_folder/code_in_a.cs", "code_folder/sample1.cs", "code_folder/sample2.cs" },
                    rootDependency.OrderBy(x => x));

                // Verify a.md markup result
                var aDependency = new HashSet <string>();
                var aMarked     = DocfxFlavoredMarked.Markup(Path.Combine(Directory.GetCurrentDirectory(), $"{uniqueFolderName}/root_folder"), a, fallbackFolders, "a_folder/a.md", dependency: aDependency);
                Assert.Equal(@"<p>markdown a.md main content start.</p>
<p>code_in_a code in a.md content start</p>
<pre><code class=""lang-cs"" name=""this is code_in_a code"">namespace code_in_a{}
</code></pre><p>code_in_a in a.md content end</p>
<p>markdown a.md a.md content end.</p>
".Replace("\r\n", "\n"), aMarked);
                Assert.Equal(
                    new[] { "../../fallback_folder/a_folder/code_in_a.cs", "code_in_a.cs" },
                    aDependency.OrderBy(x => x));
            }
            finally
            {
                EnvironmentContext.Clean();
            }
        }
Exemple #10
0
        public void TestRendererCreator()
        {
            var content = @"namespace ConsoleApplication1
{
    // <namespace>
    using System;
    using System.Collections.Generic;
    using System.IO;
    // </namespace>

    // <snippetprogram>
    class Program
    {
        static void Main(string[] args)
        {
            string s = ""\ntest"";
            int i = 100;
        }
    }
    // </snippetprogram>

    #region Helper
    internal static class Helper
    {
        #region Foo
        public static void Foo()
        {
        }
        #endregion Foo
    }
    #endregion
}";

            File.WriteAllText("Program.csdocfx", content.Replace("\r\n", "\n"));
            var p        = new TestDfmRendererPartProvider();
            var renderer = CustomizedRendererCreator.CreateRenderer(
                new DfmRenderer(),
                new[] { p },
                null);
            var engine = DocfxFlavoredMarked
                         .CreateBuilder(".")
                         .CreateDfmEngine(renderer);
            var result = engine.Markup(@"```cs
public void TestRendererCreator()
```
```cs-x
public void TestRendererCreator()
```
[!code-csdocfx[Main](Program.csdocfx#namespace ""This is root"")]
[!code-cs-xyz[](Program.csdocfx#Foo)]", "a.md");

            Assert.Equal(@"<pre><code class=""lang-cs"">public void TestRendererCreator()
</code></pre><pre class=""x""><code class=""lang-cs"">public void TestRendererCreator()
</code></pre><pre><code class=""lang-csdocfx"" name=""Main"" title=""This is root"">using System;
using System.Collections.Generic;
using System.IO;
</code></pre><pre><code class=""lang-cs-xyz"">public static void Foo()
{
}
</code></pre>".Replace("\r\n", "\n"), result);
            (renderer as IDisposable).Dispose();
            Assert.True(p.CodeRendererPartInstance.Disposed);
            if (File.Exists("Program.csdocfx"))
            {
                File.Delete("Program.csdocfx");
            }
        }
Exemple #11
0
 public DfmService(string baseDir)
 {
     _builder = DocfxFlavoredMarked.CreateBuilder(baseDir);
 }
Exemple #12
0
        public void TestSectionCornerCase(string source, string expected)
        {
            var content = DocfxFlavoredMarked.Markup(source);

            Assert.Equal(expected, content);
        }
Exemple #13
0
 public void TestDfmInGeneral(string source, string expected)
 {
     Assert.Equal(expected.Replace("\r\n", "\n"), DocfxFlavoredMarked.Markup(source));
 }
Exemple #14
0
        public MarkupResult MarkupCore(string markdown, FileAndType ft)
        {
            var html = DocfxFlavoredMarked.Markup(markdown, Path.Combine(ft.BaseDir, ft.File));
            var doc  = new HtmlDocument();

            doc.LoadHtml(html);
            var result = new MarkupResult();

            var node = doc.DocumentNode.SelectSingleNode("//yamlheader");

            if (node != null)
            {
                using (var sr = new StringReader(StringHelper.HtmlDecode(node.InnerHtml)))
                {
                    result.YamlHeader = YamlUtility.Deserialize <Dictionary <string, object> >(sr).ToImmutableDictionary();
                }
                node.Remove();
            }
            var linkToFiles = new HashSet <string>();

            foreach (var link in from n in doc.DocumentNode.Descendants()
                     where !string.Equals(n.Name, "xref", StringComparison.OrdinalIgnoreCase)
                     from attr in n.Attributes
                     where string.Equals(attr.Name, "src", StringComparison.OrdinalIgnoreCase) ||
                     string.Equals(attr.Name, "href", StringComparison.OrdinalIgnoreCase)
                     where !string.IsNullOrWhiteSpace(attr.Value)
                     select attr)
            {
                string linkFile;
                string anchor = null;
                if (PathUtility.IsRelativePath(link.Value))
                {
                    var index = link.Value.IndexOf('#');
                    if (index == -1)
                    {
                        linkFile = link.Value;
                    }
                    else if (index == 0)
                    {
                        continue;
                    }
                    else
                    {
                        linkFile = link.Value.Remove(index);
                        anchor   = link.Value.Substring(index);
                    }
                    var path = (RelativePath)ft.File + (RelativePath)linkFile;
                    if (path.ParentDirectoryCount > 0)
                    {
                        Logger.LogError($"Cannot refer path: \"{path}\" out of project.", file: ft.File);
                        throw new DocumentException($"Cannot refer path \"{path}\" out of project in file \"{ft.File}\".");
                    }
                    var file = path.GetPathFromWorkingFolder();
                    link.Value = file + anchor;
                    linkToFiles.Add(HttpUtility.UrlDecode(file));
                }
            }
            result.LinkToFiles = linkToFiles.ToImmutableArray();
            result.LinkToUids  = (from n in doc.DocumentNode.Descendants()
                                  where string.Equals(n.Name, "xref", StringComparison.OrdinalIgnoreCase)
                                  from attr in n.Attributes
                                  where string.Equals(attr.Name, "href", StringComparison.OrdinalIgnoreCase)
                                  where !string.IsNullOrWhiteSpace(attr.Value)
                                  select attr.Value).ToImmutableHashSet();
            using (var sw = new StringWriter())
            {
                doc.Save(sw);
                result.Html = sw.ToString();
            }
            return(result);
        }
Exemple #15
0
 private void Init(string phaseName)
 {
     Listener = new TestLoggerListener(phaseName);
     Logger.RegisterListener(Listener);
     DocfxFlavoredMarked.ClearBuilder();
 }
Exemple #16
0
        public void TestDfmFencesInlineLevel()
        {
            var root = @"
| Code in table | Header1 |
 ----------------- | ----------------------------
| [!code-FakeREST[REST](api.json)] | [!Code-FakeREST-i[REST-i](api.json ""This is root"")]
| [!CODE[No Language](api.json)] | [!code-js[empty](api.json)]
";

            var apiJsonContent = @"
{
   ""method"": ""GET"",
   ""resourceFormat"": ""https://outlook.office.com/api/v1.0/me/events?$select=Subject,Organizer,Start,End"",
   ""requestUrl"": ""https://outlook.office.com/api/v1.0/me/events?$select=Subject,Organizer,Start,End"",
   ""requestHeaders"": {
                ""Accept"": ""application/json""
   }
}";

            File.WriteAllText("api.json", apiJsonContent.Replace("\r\n", "\n"));
            var          dependency = new HashSet <string>();
            var          marked     = DocfxFlavoredMarked.Markup(root, "api.json", dependency: dependency);
            const string expected   = @"<table>
<thead>
<tr>
<th>Code in table</th>
<th>Header1</th>
</tr>
</thead>
<tbody>
<tr>
<td><pre><code class=""lang-FakeREST"" name=""REST"">
{
   &quot;method&quot;: &quot;GET&quot;,
   &quot;resourceFormat&quot;: &quot;https://outlook.office.com/api/v1.0/me/events?$select=Subject,Organizer,Start,End&quot;,
   &quot;requestUrl&quot;: &quot;https://outlook.office.com/api/v1.0/me/events?$select=Subject,Organizer,Start,End&quot;,
   &quot;requestHeaders&quot;: {
                &quot;Accept&quot;: &quot;application/json&quot;
   }
}
</code></pre></td>
<td><pre><code class=""lang-FakeREST-i"" name=""REST-i"" title=""This is root"">
{
   &quot;method&quot;: &quot;GET&quot;,
   &quot;resourceFormat&quot;: &quot;https://outlook.office.com/api/v1.0/me/events?$select=Subject,Organizer,Start,End&quot;,
   &quot;requestUrl&quot;: &quot;https://outlook.office.com/api/v1.0/me/events?$select=Subject,Organizer,Start,End&quot;,
   &quot;requestHeaders&quot;: {
                &quot;Accept&quot;: &quot;application/json&quot;
   }
}
</code></pre></td>
</tr>
<tr>
<td><pre><code name=""No Language"">
{
   &quot;method&quot;: &quot;GET&quot;,
   &quot;resourceFormat&quot;: &quot;https://outlook.office.com/api/v1.0/me/events?$select=Subject,Organizer,Start,End&quot;,
   &quot;requestUrl&quot;: &quot;https://outlook.office.com/api/v1.0/me/events?$select=Subject,Organizer,Start,End&quot;,
   &quot;requestHeaders&quot;: {
                &quot;Accept&quot;: &quot;application/json&quot;
   }
}
</code></pre></td>
<td><pre><code class=""lang-js"" name=""empty"">
{
   &quot;method&quot;: &quot;GET&quot;,
   &quot;resourceFormat&quot;: &quot;https://outlook.office.com/api/v1.0/me/events?$select=Subject,Organizer,Start,End&quot;,
   &quot;requestUrl&quot;: &quot;https://outlook.office.com/api/v1.0/me/events?$select=Subject,Organizer,Start,End&quot;,
   &quot;requestHeaders&quot;: {
                &quot;Accept&quot;: &quot;application/json&quot;
   }
}
</code></pre></td>
</tr>
</tbody>
</table>
";

            Assert.Equal(expected.Replace("\r\n", "\n"), marked);
            Assert.Equal(
                new[] { "api.json" },
                dependency.OrderBy(x => x));
        }
Exemple #17
0
 public DfmJsonTokenTreeService(string baseDir, IMarkdownTokenTreeValidator tokenTreeValidator)
 {
     _builder = DocfxFlavoredMarked.CreateBuilder(baseDir);
     _builder.TokenTreeValidator = tokenTreeValidator;
 }
Exemple #18
0
 private void CleanUp()
 {
     Logger.UnregisterAllListeners();
     Listener = null;
     DocfxFlavoredMarked.ClearBuilder();
 }
Exemple #19
0
        public void TestTabGroup_DifferentTabIdSet()
        {
            var listener = TestLoggerListener.CreateLoggerListenerWithPhaseEqualFilter("test!!!!");
            var options  = DocfxFlavoredMarked.CreateDefaultOptions();

            options.ShouldExportSourceInfo = true;
            var    groupId = "aupEkulau5";
            string actual;

            try
            {
                Logger.RegisterListener(listener);
                using (new LoggerPhaseScope("test!!!!"))
                {
                    actual = DocfxFlavoredMarked.Markup(null, null, options, @"# [title-a](#tab/a)
content-a
# [title-b](#tab/b)
content-b
- - -
# [title-a](#tab/a)
content-a
# [title-c](#tab/c)
content-c
- - -", "test.md");
                }
            }
            finally
            {
                Logger.UnregisterListener(listener);
            }

            var expected = $@"<div class=""tabGroup"" id=""tabgroup_{groupId}"" sourceFile=""test.md"" sourceStartLineNumber=""1"" sourceEndLineNumber=""5"">
<ul role=""tablist"">
<li role=""presentation"">
<a href=""#tabpanel_{groupId}_a"" role=""tab"" aria-controls=""tabpanel_{groupId}_a"" data-tab=""a"" tabindex=""0"" aria-selected=""true"" sourceFile=""test.md"" sourceStartLineNumber=""1"" sourceEndLineNumber=""1"">title-a</a>
</li>
<li role=""presentation"">
<a href=""#tabpanel_{groupId}_b"" role=""tab"" aria-controls=""tabpanel_{groupId}_b"" data-tab=""b"" tabindex=""-1"" sourceFile=""test.md"" sourceStartLineNumber=""3"" sourceEndLineNumber=""3"">title-b</a>
</li>
</ul>
<section id=""tabpanel_{groupId}_a"" role=""tabpanel"" data-tab=""a"">
<p sourceFile=""test.md"" sourceStartLineNumber=""2"" sourceEndLineNumber=""2"">content-a</p>
</section>
<section id=""tabpanel_{groupId}_b"" role=""tabpanel"" data-tab=""b"" aria-hidden=""true"" hidden=""hidden"">
<p sourceFile=""test.md"" sourceStartLineNumber=""4"" sourceEndLineNumber=""4"">content-b</p>
</section>
</div>
<div class=""tabGroup"" id=""tabgroup_{groupId}-1"" sourceFile=""test.md"" sourceStartLineNumber=""6"" sourceEndLineNumber=""10"">
<ul role=""tablist"">
<li role=""presentation"">
<a href=""#tabpanel_{groupId}-1_a"" role=""tab"" aria-controls=""tabpanel_{groupId}-1_a"" data-tab=""a"" tabindex=""0"" aria-selected=""true"" sourceFile=""test.md"" sourceStartLineNumber=""6"" sourceEndLineNumber=""6"">title-a</a>
</li>
<li role=""presentation"">
<a href=""#tabpanel_{groupId}-1_c"" role=""tab"" aria-controls=""tabpanel_{groupId}-1_c"" data-tab=""c"" tabindex=""-1"" sourceFile=""test.md"" sourceStartLineNumber=""8"" sourceEndLineNumber=""8"">title-c</a>
</li>
</ul>
<section id=""tabpanel_{groupId}-1_a"" role=""tabpanel"" data-tab=""a"">
<p sourceFile=""test.md"" sourceStartLineNumber=""7"" sourceEndLineNumber=""7"">content-a</p>
</section>
<section id=""tabpanel_{groupId}-1_c"" role=""tabpanel"" data-tab=""c"" aria-hidden=""true"" hidden=""hidden"">
<p sourceFile=""test.md"" sourceStartLineNumber=""9"" sourceEndLineNumber=""9"">content-c</p>
</section>
</div>
";

            Assert.Equal(expected.Replace("\r\n", "\n"), actual);
            Assert.Equal(new[] { WarningCodes.Markdown.DifferentTabIdSet }, from item in listener.Items select item.Code);
        }
Exemple #20
0
        public void TestSectionWithTextFollowed(string source)
        {
            var markedContent = DocfxFlavoredMarked.Markup(source);

            Assert.Equal("<div class=\"All\" id=\"All\"><p>Followed text\nWe should support that.</p>\n</div>\n", markedContent);
        }
Exemple #21
0
        public void TestSectionBlockLevelRecursive(string source)
        {
            var markedContent = DocfxFlavoredMarked.Markup(source);

            Assert.Equal("<div class=\"All\" id=\"All\"><p>this is out all</p>\n<div class=\"A\" id=\"A\"><p>this is A</p>\n</div>\n<div class=\"B\" id=\"B\"><p>this is B</p>\n</div>\n</div>\n", markedContent);
        }
Exemple #22
0
 public HostService(string baseDir, IEnumerable <FileModel> models)
 {
     _engine = DocfxFlavoredMarked.CreateBuilder(baseDir);
     LoadCore(models);
 }
Exemple #23
0
        public void TestSectionNoteMixture(string source)
        {
            var content = DocfxFlavoredMarked.Markup(source);

            Assert.Equal("<blockquote><p>this is blockquote</p>\n<p>this line is also in the before blockquote</p>\n</blockquote>\n<div class=\"NOTE\"><h5>NOTE</h5><p>This is note text</p>\n</div>\n<div class=\"WARNING\"><h5>WARNING</h5><p>This is warning text</p>\n</div>\n<div class=\"a\" id=\"diva\"><p>this is div with class a and id diva\ntext also in div</p>\n</div>\n<div class=\"b\" cause=\"divb\"><p>this is div with class b and cause divb</p>\n</div>\n<div class=\"IMPORTANT\"><h5>IMPORTANT</h5><p>This is imoprtant text follow div</p>\n</div>\n", content);
        }
Exemple #24
0
 public DfmService(string baseDir, ImmutableDictionary <string, string> tokens)
 {
     _builder = DocfxFlavoredMarked.CreateBuilder(baseDir);
     _tokens  = tokens;
 }
Exemple #25
0
        public void TestBlockLevelInclusion()
        {
            // -r
            //  |- root.md
            //  |- empty.md
            //  |- a
            //  |  |- refc.md
            //  |- b
            //  |  |- linkAndRefRoot.md
            //  |  |- a.md
            //  |  |- img
            //  |  |   |- img.jpg
            //  |- c
            //  |  |- c.md
            //  |- link
            //     |- link2.md
            //     |- md
            //         |- c.md
            var root = @"
[!include[linkAndRefRoot](b/linkAndRefRoot.md)]
[!include[refc](a/refc.md ""This is root"")]
[!include[refc_using_cache](a/refc.md)]
[!include[empty](empty.md)]
[!include[external](http://microsoft.com/a.md)]";

            var linkAndRefRoot = @"
Paragraph1
[link](a.md)
[!include[link2](../link/link2.md)]
![Image](img/img.jpg)
[!include[root](../root.md)]";
            var link2          = @"[link](md/c.md)";
            var refc           = @"[!include[c](../c/c.md ""This is root"")]";
            var c = @"**Hello**";

            WriteToFile("r/root.md", root);

            WriteToFile("r/a/refc.md", refc);
            WriteToFile("r/b/linkAndRefRoot.md", linkAndRefRoot);
            WriteToFile("r/link/link2.md", link2);
            WriteToFile("r/c/c.md", c);
            WriteToFile("r/empty.md", string.Empty);
            var dependency = new HashSet <string>();
            var marked     = DocfxFlavoredMarked.Markup(root, "r/root.md", dependency: dependency);

            Assert.Equal(@"<!-- BEGIN INCLUDE: Include content from &quot;r/b/linkAndRefRoot.md&quot; --><p>Paragraph1
<a href=""~/r/b/a.md"">link</a>
<!-- BEGIN INCLUDE: Include content from &quot;r/link/link2.md&quot; --><a href=""~/r/link/md/c.md"">link</a><!--END INCLUDE -->
<img src=""~/r/b/img/img.jpg"" alt=""Image"">
<!-- BEGIN ERROR INCLUDE: Unable to resolve [!include[root](../root.md)]: Circular dependency found in &quot;r/b/linkAndRefRoot.md&quot; -->[!include[root](../root.md)]<!--END ERROR INCLUDE --></p>
<!--END INCLUDE --><!-- BEGIN INCLUDE: Include content from &quot;r/a/refc.md&quot; --><!-- BEGIN INCLUDE: Include content from &quot;r/c/c.md&quot; --><p><strong>Hello</strong></p>
<!--END INCLUDE --><!--END INCLUDE --><!-- BEGIN INCLUDE: Include content from &quot;r/a/refc.md&quot; --><!-- BEGIN INCLUDE: Include content from &quot;r/c/c.md&quot; --><p><strong>Hello</strong></p>
<!--END INCLUDE --><!--END INCLUDE --><!-- BEGIN INCLUDE: Include content from &quot;r/empty.md&quot; --><!--END INCLUDE --><!-- BEGIN ERROR INCLUDE: Absolute path &quot;http://microsoft.com/a.md&quot; is not supported. -->[!include[external](http://microsoft.com/a.md)]<!--END ERROR INCLUDE -->".Replace("\r\n", "\n"), marked);
            Assert.Equal(
                new[]
            {
                "a/refc.md",
                "b/linkAndRefRoot.md",
                "c/c.md",
                "empty.md",
                "link/link2.md",
                "root.md",
            },
                dependency.OrderBy(x => x));
        }
        public void TestReadMarkdownAsOverwrite()
        {
            var content = @"---
uid: Test
remarks: Hello
---

This is unit test!";

            content = Regex.Replace(content, "\r?\n", "\r\n");
            var html     = DocfxFlavoredMarked.Markup(content);
            var baseDir  = Directory.GetCurrentDirectory();
            var fileName = "ut_ReadMarkdownAsOverwrite.md";
            var fullPath = Path.Combine(baseDir, fileName);

            File.WriteAllText(fullPath, content);
            var host = new HostService(null, Enumerable.Empty <FileModel>())
            {
                MarkdownService = new DfmServiceProvider().CreateMarkdownService(new MarkdownServiceParameters {
                    BasePath = string.Empty
                })
            };

            var ft      = new FileAndType(baseDir, fileName, DocumentType.Overwrite, null);
            var results = MarkdownReader.ReadMarkdownAsOverwrite(host, ft).ToList();

            Assert.NotNull(results);
            Assert.Equal(1, results.Count);
            Assert.Equal("Test", results[0].Uid);
            Assert.Equal("Hello", results[0].Metadata["remarks"]);
            Assert.Equal("<p>This is unit test!</p>\n", results[0].Conceptual);
            File.Delete(fileName);

            // Test conceptual content between two yamlheader
            content = @"---
uid: Test1
remarks: Hello
---
This is unit test!

---
uid: Test2
---
";
            content = Regex.Replace(content, "\r?\n", "\r\n");
            html    = DocfxFlavoredMarked.Markup(content);
            File.WriteAllText(fileName, content);
            results = MarkdownReader.ReadMarkdownAsOverwrite(host, ft).ToList();
            Assert.NotNull(results);
            Assert.Equal(2, results.Count);
            Assert.Equal("Test1", results[0].Uid);
            Assert.Equal("Test2", results[1].Uid);
            Assert.Equal("Hello", results[0].Metadata["remarks"]);
            Assert.Equal("<p>This is unit test!</p>\n", results[0].Conceptual);
            Assert.Equal(string.Empty, results[1].Conceptual);
            File.Delete(fileName);

            //invalid yamlheader is not supported
            content = @"---
uid: Test1
remarks: Hello
---
This is unit test!
---
uid: Test2
---
";
            content = Regex.Replace(content, "\r?\n", "\r\n");
            html    = DocfxFlavoredMarked.Markup(content);
            File.WriteAllText(fileName, content);
            results = MarkdownReader.ReadMarkdownAsOverwrite(host, ft).ToList();
            Assert.NotNull(results);
            Assert.Equal(1, results.Count);
            Assert.Equal("Test1", results[0].Uid);
            Assert.Equal("Hello", results[0].Metadata["remarks"]);
            Assert.Equal("<h2 id=\"this-is-unit-test-\">This is unit test!</h2>\n<h2 id=\"uid-test2\">uid: Test2</h2>\n", results[0].Conceptual);
            File.Delete(fileName);

            // Test conceptual content with extra empty line between two yamlheader
            content = @"---
uid: Test1
remarks: Hello
---


This is unit test!


---
uid: Test2
---
";
            content = Regex.Replace(content, "\r?\n", "\r\n");
            html    = DocfxFlavoredMarked.Markup(content);
            File.WriteAllText(fileName, content);
            results = MarkdownReader.ReadMarkdownAsOverwrite(host, ft).ToList();
            Assert.NotNull(results);
            Assert.Equal(2, results.Count);
            Assert.Equal("Test1", results[0].Uid);
            Assert.Equal("Test2", results[1].Uid);
            Assert.Equal("Hello", results[0].Metadata["remarks"]);
            Assert.Equal("<p>This is unit test!</p>\n", results[0].Conceptual);
            Assert.Equal(string.Empty, results[1].Conceptual);
            File.Delete(fileName);

            // Test different line ending
            content = "---\nuid: Test\nremarks: Hello\n---\nThis is unit test!\n";
            html    = DocfxFlavoredMarked.Markup(content);
            File.WriteAllText(fileName, content);
            results = MarkdownReader.ReadMarkdownAsOverwrite(host, ft).ToList();
            Assert.NotNull(results);
            Assert.Equal(1, results.Count);
            Assert.Equal("Test", results[0].Uid);
            Assert.Equal("Hello", results[0].Metadata["remarks"]);
            Assert.Equal("<p>This is unit test!</p>\n", results[0].Conceptual);
            File.Delete(fileName);
        }
Exemple #27
0
 public DfmJsonTokenTreeService(string baseDir, ImmutableDictionary <string, string> tokens, IMarkdownTokenTreeValidator tokenTreeValidator)
 {
     _builder = DocfxFlavoredMarked.CreateBuilder(baseDir);
     _builder.TokenTreeValidator = tokenTreeValidator;
     _tokens = tokens;
 }
Exemple #28
0
        public void TestFallback_Inclusion_random_name()
        {
            // -root_folder (this is also docset folder)
            //  |- root.md
            //  |- a_folder
            //  |  |- a.md
            //  |- token_folder
            //  |  |- token1.md
            // -fallback_folder
            //  |- token_folder
            //     |- token2.md

            // 1. Prepare data
            var uniqueFolderName = Path.GetRandomFileName();
            var root             = $@"1markdown root.md main content start.

[!include[a](a_folder_{uniqueFolderName}/a_{uniqueFolderName}.md ""This is a.md"")]

markdown root.md main content end.";

            var a = $@"1markdown a.md main content start.

[!include[token1](../token_folder_{uniqueFolderName}/token1_{uniqueFolderName}.md ""This is token1.md"")]
[!include[token1](../token_folder_{uniqueFolderName}/token2_{uniqueFolderName}.md ""This is token2.md"")]

markdown a.md main content end.";

            var token1 = $@"1markdown token1.md content start.

[!include[token2](token2_{uniqueFolderName}.md ""This is token2.md"")]

markdown token1.md content end.";

            var token2 = @"**1markdown token2.md main content**";

            WriteToFile($"{uniqueFolderName}/root_folder_{uniqueFolderName}/root_{uniqueFolderName}.md", root);
            WriteToFile($"{uniqueFolderName}/root_folder_{uniqueFolderName}/a_folder_{uniqueFolderName}/a_{uniqueFolderName}.md", a);
            WriteToFile($"{uniqueFolderName}/root_folder_{uniqueFolderName}/token_folder_{uniqueFolderName}/token1_{uniqueFolderName}.md", token1);
            WriteToFile($"{uniqueFolderName}/fallback_folder_{uniqueFolderName}/token_folder_{uniqueFolderName}/token2_{uniqueFolderName}.md", token2);

            try
            {
                EnvironmentContext.SetBaseDirectory($"{uniqueFolderName}/root_folder_{uniqueFolderName}");
                var fallbackFolders = new List <string> {
                    { Path.Combine(Directory.GetCurrentDirectory(), $"{uniqueFolderName}/fallback_folder_{uniqueFolderName}") }
                };
                var dependency = new HashSet <string>();
                var marked     = DocfxFlavoredMarked.Markup(Path.Combine(Directory.GetCurrentDirectory(), $"{uniqueFolderName}/root_folder_{uniqueFolderName}"), root, fallbackFolders, $"root_{uniqueFolderName}.md", dependency: dependency);
                Assert.Equal($@"<p>1markdown root.md main content start.</p>
<p>1markdown a.md main content start.</p>
<p>1markdown token1.md content start.</p>
<p><strong>1markdown token2.md main content</strong></p>
<p>markdown token1.md content end.</p>
<p><strong>1markdown token2.md main content</strong></p>
<p>markdown a.md main content end.</p>
<p>markdown root.md main content end.</p>
".Replace("\r\n", "\n"), marked);
                Assert.Equal(
                    new[] { $"../fallback_folder_{uniqueFolderName}/token_folder_{uniqueFolderName}/token2_{uniqueFolderName}.md", $"a_folder_{uniqueFolderName}/a_{uniqueFolderName}.md", $"token_folder_{uniqueFolderName}/token1_{uniqueFolderName}.md", $"token_folder_{uniqueFolderName}/token2_{uniqueFolderName}.md" },
                    dependency.OrderBy(x => x));
            }
            finally
            {
                EnvironmentContext.Clean();
            }
        }
Exemple #29
0
        public void TestReadMarkdownAsOverwrite()
        {
            var content = @"---
uid: Test
remarks: Hello
---

This is unit test!";

            content = Regex.Replace(content, "\r?\n", "\r\n");
            var html     = DocfxFlavoredMarked.Markup(content);
            var baseDir  = Directory.GetCurrentDirectory();
            var fileName = "ut_ReadMarkdownAsOverwrite.md";
            var fullPath = Path.Combine(baseDir, fileName);

            File.WriteAllText(fullPath, content);
            var host = new HostService(null, Enumerable.Empty <FileModel>())
            {
                MarkdownService = new DfmServiceProvider().CreateMarkdownService(new MarkdownServiceParameters {
                    BasePath = string.Empty
                }),
                SourceFiles = ImmutableDictionary.Create <string, FileAndType>()
            };

            var ft      = new FileAndType(baseDir, fileName, DocumentType.Overwrite);
            var results = MarkdownReader.ReadMarkdownAsOverwrite(host, ft).ToList();

            Assert.NotNull(results);
            Assert.Equal(1, results.Count);
            Assert.Equal("Test", results[0].Uid);
            Assert.Equal("Hello", results[0].Metadata["remarks"]);
            Assert.Equal("<p sourcefile=\"ut_ReadMarkdownAsOverwrite.md\" sourcestartlinenumber=\"6\" sourceendlinenumber=\"6\">This is unit test!</p>\n", results[0].Conceptual);
            File.Delete(fileName);

            // Test conceptual content between two yamlheader
            content = @"---
uid: Test1
remarks: Hello
---
This is unit test!

---
uid: Test2
---
";
            content = Regex.Replace(content, "\r?\n", "\r\n");
            html    = DocfxFlavoredMarked.Markup(content);
            File.WriteAllText(fileName, content);
            results = MarkdownReader.ReadMarkdownAsOverwrite(host, ft).ToList();
            Assert.NotNull(results);
            Assert.Equal(2, results.Count);
            Assert.Equal("Test1", results[0].Uid);
            Assert.Equal("Test2", results[1].Uid);
            Assert.Equal("Hello", results[0].Metadata["remarks"]);
            Assert.Equal("<p sourcefile=\"ut_ReadMarkdownAsOverwrite.md\" sourcestartlinenumber=\"5\" sourceendlinenumber=\"5\">This is unit test!</p>\n", results[0].Conceptual);
            Assert.Equal(string.Empty, results[1].Conceptual);
            File.Delete(fileName);

            //invalid yamlheader is not supported
            content = @"---
uid: Test1
remarks: Hello
---
This is unit test!
---
uid: Test2
---
";
            content = Regex.Replace(content, "\r?\n", "\r\n");
            html    = DocfxFlavoredMarked.Markup(content);
            File.WriteAllText(fileName, content);
            results = MarkdownReader.ReadMarkdownAsOverwrite(host, ft).ToList();
            Assert.NotNull(results);
            Assert.Equal(1, results.Count);
            Assert.Equal("Test1", results[0].Uid);
            Assert.Equal("Hello", results[0].Metadata["remarks"]);
            Assert.Equal("<h2 id=\"this-is-unit-test\" sourcefile=\"ut_ReadMarkdownAsOverwrite.md\" sourcestartlinenumber=\"5\" sourceendlinenumber=\"6\">This is unit test!</h2>\n<h2 id=\"uid-test2\" sourcefile=\"ut_ReadMarkdownAsOverwrite.md\" sourcestartlinenumber=\"7\" sourceendlinenumber=\"8\">uid: Test2</h2>\n", results[0].Conceptual);
            File.Delete(fileName);

            // Test conceptual content with extra empty line between two yamlheader
            content = @"---
uid: Test1
remarks: Hello
---


This is unit test!


---
uid: Test2
---
";
            content = Regex.Replace(content, "\r?\n", "\r\n");
            html    = DocfxFlavoredMarked.Markup(content);
            File.WriteAllText(fileName, content);
            results = MarkdownReader.ReadMarkdownAsOverwrite(host, ft).ToList();
            Assert.NotNull(results);
            Assert.Equal(2, results.Count);
            Assert.Equal("Test1", results[0].Uid);
            Assert.Equal("Test2", results[1].Uid);
            Assert.Equal("Hello", results[0].Metadata["remarks"]);
            Assert.Equal("<p sourcefile=\"ut_ReadMarkdownAsOverwrite.md\" sourcestartlinenumber=\"7\" sourceendlinenumber=\"7\">This is unit test!</p>\n", results[0].Conceptual);
            Assert.Equal(string.Empty, results[1].Conceptual);
            File.Delete(fileName);

            // Test different line ending
            content = "---\nuid: Test\nremarks: Hello\n---\nThis is unit test!\n";
            html    = DocfxFlavoredMarked.Markup(content);
            File.WriteAllText(fileName, content);
            results = MarkdownReader.ReadMarkdownAsOverwrite(host, ft).ToList();
            Assert.NotNull(results);
            Assert.Equal(1, results.Count);
            Assert.Equal("Test", results[0].Uid);
            Assert.Equal("Hello", results[0].Metadata["remarks"]);
            Assert.Equal("<p sourcefile=\"ut_ReadMarkdownAsOverwrite.md\" sourcestartlinenumber=\"5\" sourceendlinenumber=\"5\">This is unit test!</p>\n", results[0].Conceptual);
            File.Delete(fileName);

            // Test link to files and Uids in overwrite document
            content = @"---
uid: Test
remarks: Hello
---
@NotExistUid

[Not exist link](link.md)

This is unit test!";
            content = Regex.Replace(content, "\r?\n", "\r\n");
            html    = DocfxFlavoredMarked.Markup(content);
            File.WriteAllText(fileName, content);
            results = MarkdownReader.ReadMarkdownAsOverwrite(host, ft).ToList();
            Assert.NotNull(results);
            Assert.Equal(1, results.Count);
            Assert.Equal("Test", results[0].Uid);
            Assert.Equal("Hello", results[0].Metadata["remarks"]);
            Assert.Equal(1, results[0].LinkToFiles.Count);
            Assert.Equal("~/link.md", results[0].LinkToFiles.ElementAt(0));
            Assert.Equal(1, results[0].LinkToUids.Count);
            Assert.Equal("NotExistUid", results[0].LinkToUids.ElementAt(0));
            Assert.Equal(@"<p sourcefile=""ut_ReadMarkdownAsOverwrite.md"" sourcestartlinenumber=""5"" sourceendlinenumber=""5""><xref href=""NotExistUid"" data-throw-if-not-resolved=""False"" data-raw-source=""@NotExistUid"" sourcefile=""ut_ReadMarkdownAsOverwrite.md"" sourcestartlinenumber=""5"" sourceendlinenumber=""5""></xref></p>
<p sourcefile=""ut_ReadMarkdownAsOverwrite.md"" sourcestartlinenumber=""7"" sourceendlinenumber=""7""><a href=""link.md"" data-raw-source=""[Not exist link](link.md)"" sourcefile=""ut_ReadMarkdownAsOverwrite.md"" sourcestartlinenumber=""7"" sourceendlinenumber=""7"">Not exist link</a></p>
<p sourcefile=""ut_ReadMarkdownAsOverwrite.md"" sourcestartlinenumber=""9"" sourceendlinenumber=""9"">This is unit test!</p>
".Replace("\r\n", "\n"),
                         results[0].Conceptual);
            File.Delete(fileName);
        }
 public void Parse(string source, string expected)
 {
     Assert.Equal(expected, DocfxFlavoredMarked.Markup(source));
 }