diff --git a/src/Markdig.Tests/Markdig.Tests.csproj b/src/Markdig.Tests/Markdig.Tests.csproj index 9e7fc9688..bbb6f935d 100644 --- a/src/Markdig.Tests/Markdig.Tests.csproj +++ b/src/Markdig.Tests/Markdig.Tests.csproj @@ -65,6 +65,7 @@ + diff --git a/src/Markdig.Tests/TestRelativeUrlReplacement.cs b/src/Markdig.Tests/TestRelativeUrlReplacement.cs new file mode 100644 index 000000000..edf9b83f3 --- /dev/null +++ b/src/Markdig.Tests/TestRelativeUrlReplacement.cs @@ -0,0 +1,48 @@ +using System; +using System.IO; +using Markdig.Parsers; +using Markdig.Renderers; +using NUnit.Framework; + +namespace Markdig.Tests +{ + public class TestRelativeUrlReplacement + { + [Test] + public void ReplacesRelativeLinks() + { + TestSpec("https://example.com", "Link: [hello](/relative.jpg)", "https://example.com/relative.jpg"); + TestSpec("https://example.com", "Link: [hello](relative.jpg)", "https://example.com/relative.jpg"); + TestSpec("https://example.com/", "Link: [hello](/relative.jpg?a=b)", "https://example.com/relative.jpg?a=b"); + TestSpec("https://example.com/", "Link: [hello](relative.jpg#x)", "https://example.com/relative.jpg#x"); + TestSpec(null, "Link: [hello](relative.jpg)", "relative.jpg"); + TestSpec(null, "Link: [hello](/relative.jpg)", "/relative.jpg"); + TestSpec("https://example.com", "Link: [hello](/relative.jpg)", "https://example.com/relative.jpg"); + } + + [Test] + public void ReplacesRelativeImageSources() + { + TestSpec("https://example.com", "Image: ![alt text](/image.jpg)", "https://example.com/image.jpg"); + TestSpec("https://example.com", "Image: ![alt text](image.jpg \"title\")", "https://example.com/image.jpg"); + TestSpec(null, "Image: ![alt text](/image.jpg)", "/image.jpg"); + } + + public static void TestSpec(string baseUrl, string markdown, string expectedLink) + { + var pipeline = new MarkdownPipelineBuilder().Build(); + + var writer = new StringWriter(); + var renderer = new HtmlRenderer(writer); + if (baseUrl != null) + renderer.BaseUrl = new Uri(baseUrl); + pipeline.Setup(renderer); + + var document = MarkdownParser.Parse(markdown, pipeline); + renderer.Render(document); + writer.Flush(); + + Assert.That(writer.ToString(), Contains.Substring("=\"" + expectedLink + "\"")); + } + } +} \ No newline at end of file diff --git a/src/Markdig/Renderers/HtmlRenderer.cs b/src/Markdig/Renderers/HtmlRenderer.cs index 68ceab42f..f529a17e2 100644 --- a/src/Markdig/Renderers/HtmlRenderer.cs +++ b/src/Markdig/Renderers/HtmlRenderer.cs @@ -75,6 +75,11 @@ public HtmlRenderer(TextWriter writer) : base(writer) public bool UseNonAsciiNoEscape { get; set; } + /// + /// Gets a value to use as the base url for all relative links + /// + public Uri BaseUrl { get; set; } + /// /// Writes the content escaped for HTML. /// @@ -192,6 +197,11 @@ public HtmlRenderer WriteEscapeUrl(string content) if (content == null) return this; + if (BaseUrl != null && !Uri.TryCreate(content, UriKind.Absolute, out Uri _)) + { + content = new Uri(BaseUrl, content).AbsoluteUri; + } + int previousPosition = 0; int length = content.Length;