| @@ -207,7 +207,15 @@ namespace Docnet | |||||
| return string.IsNullOrWhiteSpace(rawIncludeFolder) ? "Includes" : rawIncludeFolder; | return string.IsNullOrWhiteSpace(rawIncludeFolder) ? "Includes" : rawIncludeFolder; | ||||
| } | } | ||||
| } | } | ||||
| public bool ConvertLocalLinks | |||||
| { | |||||
| get | |||||
| { | |||||
| return _configData.ConvertLocalLinks ?? false; | |||||
| } | |||||
| } | |||||
| public string ThemeName | public string ThemeName | ||||
| { | { | ||||
| get | get | ||||
| @@ -68,7 +68,7 @@ namespace Docnet | |||||
| this.MarkdownFromFile = File.ReadAllText(sourceFile, Encoding.UTF8); | this.MarkdownFromFile = File.ReadAllText(sourceFile, Encoding.UTF8); | ||||
| // Check if the content contains @@include tag | // Check if the content contains @@include tag | ||||
| content = Utils.IncludeProcessor(this.MarkdownFromFile, Utils.MakeAbsolutePath(activeConfig.Source, activeConfig.IncludeFolder)); | content = Utils.IncludeProcessor(this.MarkdownFromFile, Utils.MakeAbsolutePath(activeConfig.Source, activeConfig.IncludeFolder)); | ||||
| content = Utils.ConvertMarkdownToHtml(content, Path.GetDirectoryName(destinationFile), activeConfig.Destination, sourceFile, _relativeH2LinksOnPage); | |||||
| content = Utils.ConvertMarkdownToHtml(content, Path.GetDirectoryName(destinationFile), activeConfig.Destination, sourceFile, _relativeH2LinksOnPage, activeConfig.ConvertLocalLinks); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -90,7 +90,7 @@ namespace Docnet | |||||
| defaultMarkdown.AppendFormat("* [{0}]({1}{2}){3}", sibling.Name, relativePathToRoot, HttpUtility.UrlPathEncode(sibling.TargetURL), Environment.NewLine); | defaultMarkdown.AppendFormat("* [{0}]({1}{2}){3}", sibling.Name, relativePathToRoot, HttpUtility.UrlPathEncode(sibling.TargetURL), Environment.NewLine); | ||||
| } | } | ||||
| defaultMarkdown.Append(Environment.NewLine); | defaultMarkdown.Append(Environment.NewLine); | ||||
| content = Utils.ConvertMarkdownToHtml(defaultMarkdown.ToString(), Path.GetDirectoryName(destinationFile), activeConfig.Destination, string.Empty, _relativeH2LinksOnPage); | |||||
| content = Utils.ConvertMarkdownToHtml(defaultMarkdown.ToString(), Path.GetDirectoryName(destinationFile), activeConfig.Destination, string.Empty, _relativeH2LinksOnPage, activeConfig.ConvertLocalLinks); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -37,19 +37,20 @@ namespace Docnet | |||||
| /// Regex expression used to parse @@include(filename.html) tag. | /// Regex expression used to parse @@include(filename.html) tag. | ||||
| /// </summary> | /// </summary> | ||||
| private static Regex includeRegex = new Regex(@"@@include\((.*)\)", RegexOptions.IgnoreCase | RegexOptions.Compiled); | private static Regex includeRegex = new Regex(@"@@include\((.*)\)", RegexOptions.IgnoreCase | RegexOptions.Compiled); | ||||
| #endregion | |||||
| /// <summary> | |||||
| /// Converts the markdown to HTML. | |||||
| /// </summary> | |||||
| /// <param name="toConvert">The markdown string to convert.</param> | |||||
| /// <param name="destinationDocumentPath">The document path (without the document filename).</param> | |||||
| /// <param name="siteRoot">The site root.</param> | |||||
| /// <param name="sourceDocumentFilename">the filename of the source markdown file</param> | |||||
| /// <param name="createdAnchorCollector">The created anchor collector, for ToC sublinks for H2 headers.</param> | |||||
| /// <returns></returns> | |||||
| public static string ConvertMarkdownToHtml(string toConvert, string destinationDocumentPath, string siteRoot, string sourceDocumentFilename, | |||||
| List<Tuple<string, string>> createdAnchorCollector) | |||||
| #endregion | |||||
| /// <summary> | |||||
| /// Converts the markdown to HTML. | |||||
| /// </summary> | |||||
| /// <param name="toConvert">The markdown string to convert.</param> | |||||
| /// <param name="destinationDocumentPath">The document path (without the document filename).</param> | |||||
| /// <param name="siteRoot">The site root.</param> | |||||
| /// <param name="sourceDocumentFilename">the filename of the source markdown file</param> | |||||
| /// <param name="createdAnchorCollector">The created anchor collector, for ToC sublinks for H2 headers.</param> | |||||
| /// <param name="convertLocalLinks">if set to <c>true</c>, convert local links to md files to target files.</param> | |||||
| /// <returns></returns> | |||||
| public static string ConvertMarkdownToHtml(string toConvert, string destinationDocumentPath, string siteRoot, string sourceDocumentFilename, | |||||
| List<Tuple<string, string>> createdAnchorCollector, bool convertLocalLinks) | |||||
| { | { | ||||
| var parser = new MarkdownDeep.Markdown | var parser = new MarkdownDeep.Markdown | ||||
| { | { | ||||
| @@ -58,7 +59,8 @@ namespace Docnet | |||||
| AutoHeadingIDs = true, | AutoHeadingIDs = true, | ||||
| NewWindowForExternalLinks = true, | NewWindowForExternalLinks = true, | ||||
| DocNetMode = true, | DocNetMode = true, | ||||
| DestinationDocumentLocation = destinationDocumentPath, | |||||
| ConvertLocalLinks = convertLocalLinks, | |||||
| DestinationDocumentLocation = destinationDocumentPath, | |||||
| DocumentRoot = siteRoot, | DocumentRoot = siteRoot, | ||||
| SourceDocumentFilename = sourceDocumentFilename, | SourceDocumentFilename = sourceDocumentFilename, | ||||
| HtmlClassTitledImages = "figure", | HtmlClassTitledImages = "figure", | ||||
| @@ -58,9 +58,36 @@ namespace MarkdownDeep | |||||
| { | { | ||||
| HtmlTag tag = new HtmlTag("a"); | HtmlTag tag = new HtmlTag("a"); | ||||
| var url = this.Url; | |||||
| if (m.DocNetMode && m.ConvertLocalLinks) | |||||
| { | |||||
| // A few requirements before we can convert local links: | |||||
| // 1. Link contains .md | |||||
| // 2. Link is relative | |||||
| // 3. Link is included in the index | |||||
| var index = url.LastIndexOf(".md", StringComparison.OrdinalIgnoreCase); | |||||
| if (index >= 0) | |||||
| { | |||||
| Uri uri; | |||||
| if (Uri.TryCreate(url, UriKind.RelativeOrAbsolute, out uri)) | |||||
| { | |||||
| if (!uri.IsAbsoluteUri) | |||||
| { | |||||
| // TODO: Check if link exists in the ToC | |||||
| var existsInTableOfContents = true; | |||||
| if (existsInTableOfContents) | |||||
| { | |||||
| url = url.Remove(index, ".md".Length).Insert(index, ".htm"); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| // encode url | // encode url | ||||
| StringBuilder sb = m.GetStringBuilder(); | StringBuilder sb = m.GetStringBuilder(); | ||||
| Utils.SmartHtmlEncodeAmpsAndAngles(sb, this.Url); | |||||
| Utils.SmartHtmlEncodeAmpsAndAngles(sb, url); | |||||
| tag.attributes["href"] = sb.ToString(); | tag.attributes["href"] = sb.ToString(); | ||||
| // encode title | // encode title | ||||
| @@ -846,10 +846,16 @@ namespace MarkdownDeep | |||||
| /// </summary> | /// </summary> | ||||
| public bool DocNetMode { get; set; } | public bool DocNetMode { get; set; } | ||||
| // When set, all html block level elements automatically support | |||||
| // markdown syntax within them. | |||||
| // (Similar to Pandoc's handling of markdown in html) | |||||
| public bool MarkdownInHtml | |||||
| /// <summary> | |||||
| /// Gets or sets a value indicating whether local links to markdown files should be converted as well. | |||||
| /// </summary> | |||||
| public bool ConvertLocalLinks { get; set; } | |||||
| // When set, all html block level elements automatically support | |||||
| // markdown syntax within them. | |||||
| // (Similar to Pandoc's handling of markdown in html) | |||||
| public bool MarkdownInHtml | |||||
| { | { | ||||
| get; | get; | ||||
| set; | set; | ||||
| @@ -0,0 +1,33 @@ | |||||
| using System.Collections.Generic; | |||||
| using NUnit.Framework; | |||||
| namespace MarkdownDeepTests | |||||
| { | |||||
| [TestFixture] | |||||
| class LocalLinkTests | |||||
| { | |||||
| public static IEnumerable<TestCaseData> GetTests_locallinks_enabled() | |||||
| { | |||||
| return Utils.GetTests("locallinks_enabled"); | |||||
| } | |||||
| [Test, TestCaseSource("GetTests_locallinks_enabled")] | |||||
| public void Test_locallinks_enabled(string resourceName) | |||||
| { | |||||
| Utils.RunResourceTest(resourceName); | |||||
| } | |||||
| public static IEnumerable<TestCaseData> GetTests_locallinks_disabled() | |||||
| { | |||||
| return Utils.GetTests("locallinks_disabled"); | |||||
| } | |||||
| [Test, TestCaseSource("GetTests_locallinks_disabled")] | |||||
| public void Test_locallinks_disabled(string resourceName) | |||||
| { | |||||
| Utils.RunResourceTest(resourceName); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -76,6 +76,7 @@ | |||||
| <Compile Include="AutoHeaderIDTests.cs" /> | <Compile Include="AutoHeaderIDTests.cs" /> | ||||
| <Compile Include="DocNetMode.cs" /> | <Compile Include="DocNetMode.cs" /> | ||||
| <Compile Include="GithubMode.cs" /> | <Compile Include="GithubMode.cs" /> | ||||
| <Compile Include="LocalLinkTests.cs" /> | |||||
| <Compile Include="TableSpecTests.cs" /> | <Compile Include="TableSpecTests.cs" /> | ||||
| <Compile Include="ExtraMode.cs" /> | <Compile Include="ExtraMode.cs" /> | ||||
| <Compile Include="SafeModeTests.cs" /> | <Compile Include="SafeModeTests.cs" /> | ||||
| @@ -401,6 +402,12 @@ | |||||
| </None> | </None> | ||||
| <None Include="packages.config" /> | <None Include="packages.config" /> | ||||
| <EmbeddedResource Include="testfiles\mdtest11\Images%28Titled%29.text" /> | <EmbeddedResource Include="testfiles\mdtest11\Images%28Titled%29.text" /> | ||||
| <EmbeddedResource Include="testfiles\locallinks_enabled\markdown-readme%28DocNetMode%29%28ConvertLocalLinks%29.text" /> | |||||
| <EmbeddedResource Include="testfiles\locallinks_enabled\target1.text" /> | |||||
| <EmbeddedResource Include="testfiles\locallinks_enabled\target2.text" /> | |||||
| <EmbeddedResource Include="testfiles\locallinks_disabled\markdown-readme%28DocNetMode%29.text" /> | |||||
| <EmbeddedResource Include="testfiles\locallinks_disabled\target1.text" /> | |||||
| <EmbeddedResource Include="testfiles\locallinks_disabled\target2.text" /> | |||||
| </ItemGroup> | </ItemGroup> | ||||
| <ItemGroup> | <ItemGroup> | ||||
| <EmbeddedResource Include="testfiles\githubmode\FencedCodeBlocksAlt%28GitHubMode%29.html" /> | <EmbeddedResource Include="testfiles\githubmode\FencedCodeBlocksAlt%28GitHubMode%29.html" /> | ||||
| @@ -487,6 +494,24 @@ | |||||
| <ItemGroup> | <ItemGroup> | ||||
| <EmbeddedResource Include="testfiles\docnetmode\Snippet%28DocNetMode%29.txt" /> | <EmbeddedResource Include="testfiles\docnetmode\Snippet%28DocNetMode%29.txt" /> | ||||
| </ItemGroup> | </ItemGroup> | ||||
| <ItemGroup> | |||||
| <EmbeddedResource Include="testfiles\locallinks_enabled\markdown-readme%28DocNetMode%29%28ConvertLocalLinks%29.html" /> | |||||
| </ItemGroup> | |||||
| <ItemGroup> | |||||
| <EmbeddedResource Include="testfiles\locallinks_enabled\target1.html" /> | |||||
| </ItemGroup> | |||||
| <ItemGroup> | |||||
| <EmbeddedResource Include="testfiles\locallinks_enabled\target2.html" /> | |||||
| </ItemGroup> | |||||
| <ItemGroup> | |||||
| <EmbeddedResource Include="testfiles\locallinks_disabled\markdown-readme%28DocNetMode%29.html" /> | |||||
| </ItemGroup> | |||||
| <ItemGroup> | |||||
| <EmbeddedResource Include="testfiles\locallinks_disabled\target1.html" /> | |||||
| </ItemGroup> | |||||
| <ItemGroup> | |||||
| <EmbeddedResource Include="testfiles\locallinks_disabled\target2.html" /> | |||||
| </ItemGroup> | |||||
| <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | ||||
| <!-- To modify your build process, add your task inside one of the targets below and uncomment it. | <!-- To modify your build process, add your task inside one of the targets below and uncomment it. | ||||
| Other similar extension points exist, see Microsoft.Common.targets. | Other similar extension points exist, see Microsoft.Common.targets. | ||||
| @@ -126,7 +126,8 @@ namespace MarkdownDeepTests | |||||
| md.ExtraMode = resourceName.IndexOf("(ExtraMode)") >= 0; | md.ExtraMode = resourceName.IndexOf("(ExtraMode)") >= 0; | ||||
| md.GitHubCodeBlocks = resourceName.IndexOf("(GitHubMode)") >= 0; | md.GitHubCodeBlocks = resourceName.IndexOf("(GitHubMode)") >= 0; | ||||
| md.DocNetMode = resourceName.IndexOf("(DocNetMode") >= 0; | md.DocNetMode = resourceName.IndexOf("(DocNetMode") >= 0; | ||||
| md.MarkdownInHtml = resourceName.IndexOf("(MarkdownInHtml)") >= 0; | |||||
| md.ConvertLocalLinks = resourceName.IndexOf("(ConvertLocalLinks") >= 0; | |||||
| md.MarkdownInHtml = resourceName.IndexOf("(MarkdownInHtml)") >= 0; | |||||
| md.AutoHeadingIDs = resourceName.IndexOf("(AutoHeadingIDs)") >= 0; | md.AutoHeadingIDs = resourceName.IndexOf("(AutoHeadingIDs)") >= 0; | ||||
| if(resourceName.IndexOf("(Titled)") >= 0) | if(resourceName.IndexOf("(Titled)") >= 0) | ||||
| { | { | ||||
| @@ -0,0 +1,5 @@ | |||||
| <h1>Markdown</h1> | |||||
| <p> <a href="https://github.com/FransBouma">Remote link</a> </p> | |||||
| <p> <a href="./target1.md">Local 1</a> </p> | |||||
| <p> <a href="./target2.md">Local 2</a> </p> | |||||
| @@ -0,0 +1,8 @@ | |||||
| Markdown | |||||
| ======== | |||||
| [Remote link](https://github.com/FransBouma) | |||||
| [Local 1](./target1.md) | |||||
| [Local 2](./target2.md) | |||||
| @@ -0,0 +1,3 @@ | |||||
| <h1>Markdown</h1> | |||||
| <p> This is target file 1. </p> | |||||
| @@ -0,0 +1,4 @@ | |||||
| Markdown | |||||
| ======== | |||||
| This is target file 1. | |||||
| @@ -0,0 +1,3 @@ | |||||
| <h1>Markdown</h1> | |||||
| <p> This is target file 2. </p> | |||||
| @@ -0,0 +1,4 @@ | |||||
| Markdown | |||||
| ======== | |||||
| This is target file 2. | |||||
| @@ -0,0 +1,5 @@ | |||||
| <h1>Markdown</h1> | |||||
| <p> <a href="https://github.com/FransBouma">Remote link</a> </p> | |||||
| <p> <a href="./target1.htm">Local 1</a> </p> | |||||
| <p> <a href="./target2.htm">Local 2</a> </p> | |||||
| @@ -0,0 +1,8 @@ | |||||
| Markdown | |||||
| ======== | |||||
| [Remote link](https://github.com/FransBouma) | |||||
| [Local 1](./target1.md) | |||||
| [Local 2](./target2.md) | |||||
| @@ -0,0 +1,3 @@ | |||||
| <h1>Markdown</h1> | |||||
| <p> This is target file 1. </p> | |||||
| @@ -0,0 +1,4 @@ | |||||
| Markdown | |||||
| ======== | |||||
| This is target file 1. | |||||
| @@ -0,0 +1,3 @@ | |||||
| <h1>Markdown</h1> | |||||
| <p> This is target file 2. </p> | |||||
| @@ -0,0 +1,4 @@ | |||||
| Markdown | |||||
| ======== | |||||
| This is target file 2. | |||||