@@ -307,6 +307,25 @@ namespace Docnet | |||||
} | } | ||||
} | } | ||||
public UrlFormatting UrlFormatting | |||||
{ | |||||
get | |||||
{ | |||||
var urlFormatting = UrlFormatting.None; | |||||
var urlFormattingAsString = (string)_configData.UrlFormatting; | |||||
if (!string.IsNullOrWhiteSpace(urlFormattingAsString)) | |||||
{ | |||||
if (!Enum.TryParse(urlFormattingAsString, true, out urlFormatting)) | |||||
{ | |||||
urlFormatting = UrlFormatting.None; | |||||
} | |||||
} | |||||
return urlFormatting; | |||||
} | |||||
} | |||||
public NavigationLevel Pages | public NavigationLevel Pages | ||||
{ | { | ||||
get | get | ||||
@@ -68,6 +68,8 @@ | |||||
<Compile Include="SearchIndexEntry.cs" /> | <Compile Include="SearchIndexEntry.cs" /> | ||||
<Compile Include="SimpleNavigationElement.cs" /> | <Compile Include="SimpleNavigationElement.cs" /> | ||||
<Compile Include="INavigationElementExtensions.cs" /> | <Compile Include="INavigationElementExtensions.cs" /> | ||||
<Compile Include="StringExtensions.cs" /> | |||||
<Compile Include="UrlFormatting.cs" /> | |||||
<Compile Include="Utils.cs" /> | <Compile Include="Utils.cs" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
@@ -45,13 +45,7 @@ namespace Docnet | |||||
return 1; | return 1; | ||||
} | } | ||||
var navigationContext = new NavigationContext | |||||
{ | |||||
MaxLevel = _loadedConfig.MaxLevelInToC, | |||||
PathSpecification = _loadedConfig.PathSpecification, | |||||
StripIndexHtm = _loadedConfig.StripIndexHtm | |||||
}; | |||||
var navigationContext = new NavigationContext(_loadedConfig.PathSpecification, _loadedConfig.UrlFormatting, _loadedConfig.MaxLevelInToC, _loadedConfig.StripIndexHtm); | |||||
GeneratePages(navigationContext); | GeneratePages(navigationContext); | ||||
return 0; | return 0; | ||||
} | } | ||||
@@ -79,7 +73,7 @@ namespace Docnet | |||||
return null; | return null; | ||||
} | } | ||||
var navigationContext = new NavigationContext(config.PathSpecification, config.MaxLevelInToC, config.StripIndexHtm); | |||||
var navigationContext = new NavigationContext(config.PathSpecification, config.UrlFormatting, config.MaxLevelInToC, config.StripIndexHtm); | |||||
var indexElement = config.Pages.GetIndexElement(navigationContext); | var indexElement = config.Pages.GetIndexElement(navigationContext); | ||||
if(indexElement == null) | if(indexElement == null) | ||||
@@ -4,21 +4,21 @@ | |||||
{ | { | ||||
public NavigationContext() | public NavigationContext() | ||||
{ | { | ||||
MaxLevel = 2; | |||||
this.MaxLevel = 2; | |||||
} | } | ||||
public NavigationContext(PathSpecification pathSpecification, int maxLevel, bool stripIndexHtm) | |||||
public NavigationContext(PathSpecification pathSpecification, UrlFormatting urlFormatting, int maxLevel, bool stripIndexHtm) | |||||
: this() | : this() | ||||
{ | { | ||||
PathSpecification = pathSpecification; | PathSpecification = pathSpecification; | ||||
MaxLevel = maxLevel; | |||||
UrlFormatting = urlFormatting; | |||||
MaxLevel = maxLevel; | |||||
StripIndexHtm = stripIndexHtm; | StripIndexHtm = stripIndexHtm; | ||||
} | } | ||||
public PathSpecification PathSpecification { get; set; } | public PathSpecification PathSpecification { get; set; } | ||||
public int MaxLevel { get; set; } | |||||
public UrlFormatting UrlFormatting { get; set; } | |||||
public int MaxLevel { get; set; } | |||||
public bool StripIndexHtm { get; set; } | public bool StripIndexHtm { get; set; } | ||||
} | } | ||||
} | } |
@@ -305,7 +305,20 @@ namespace Docnet | |||||
} | } | ||||
} | } | ||||
var nameToUse = this.Name.Replace(".", "").Replace('/', '_').Replace("\\", "_").Replace(":", "").Replace(" ", ""); | |||||
var nameToUse = string.Empty; | |||||
switch (navigationContext.UrlFormatting) | |||||
{ | |||||
case UrlFormatting.None: | |||||
// Backwards compatibility mode | |||||
nameToUse = this.Name.Replace(".", "").Replace('/', '_').Replace("\\", "_").Replace(":", "").Replace(" ", ""); | |||||
break; | |||||
default: | |||||
nameToUse = this.Name.ApplyUrlFormatting(navigationContext.UrlFormatting); | |||||
break; | |||||
} | |||||
if (string.IsNullOrWhiteSpace(nameToUse)) | if (string.IsNullOrWhiteSpace(nameToUse)) | ||||
{ | { | ||||
return null; | return null; | ||||
@@ -226,14 +226,18 @@ namespace Docnet | |||||
{ | { | ||||
if (_targetURLForHTML == null) | if (_targetURLForHTML == null) | ||||
{ | { | ||||
_targetURLForHTML = (this.Value ?? string.Empty); | |||||
var toReplace = ".md"; | |||||
var toReplace = "mdext"; | |||||
var replacement = ".htm"; | var replacement = ".htm"; | ||||
var value = (this.Value ?? string.Empty); | |||||
// Replace with custom extension because url formatting might optimize the extension | |||||
value = value.Replace(".md", toReplace); | |||||
_targetURLForHTML = value.ApplyUrlFormatting(navigationContext.UrlFormatting); | |||||
if (navigationContext.PathSpecification == PathSpecification.RelativeAsFolder) | if (navigationContext.PathSpecification == PathSpecification.RelativeAsFolder) | ||||
{ | { | ||||
if (!IsIndexElement && !_targetURLForHTML.EndsWith("index.md", StringComparison.InvariantCultureIgnoreCase)) | |||||
if (!IsIndexElement && !_targetURLForHTML.EndsWith($"index{toReplace}", StringComparison.InvariantCultureIgnoreCase)) | |||||
{ | { | ||||
replacement = "/index.htm"; | replacement = "/index.htm"; | ||||
} | } | ||||
@@ -0,0 +1,57 @@ | |||||
using System; | |||||
using System.Text.RegularExpressions; | |||||
namespace Docnet | |||||
{ | |||||
internal static class StringExtensions | |||||
{ | |||||
public static string ApplyUrlFormatting(this string value, UrlFormatting urlFormatting) | |||||
{ | |||||
var finalValue = string.Empty; | |||||
string replacementValue = null; | |||||
switch (urlFormatting) | |||||
{ | |||||
case UrlFormatting.None: | |||||
finalValue = value; | |||||
break; | |||||
case UrlFormatting.Strip: | |||||
replacementValue = string.Empty; | |||||
break; | |||||
case UrlFormatting.Dashes: | |||||
replacementValue = "-"; | |||||
break; | |||||
default: | |||||
throw new ArgumentOutOfRangeException(nameof(urlFormatting), urlFormatting, null); | |||||
} | |||||
if (replacementValue != null) | |||||
{ | |||||
var doubleReplacementValue = replacementValue + replacementValue; | |||||
var regEx = new Regex("[^a-zA-Z0-9 -]"); | |||||
var splitted = value.Split(new[] { "/", "\\" }, StringSplitOptions.RemoveEmptyEntries); | |||||
for(var i = 0; i < splitted.Length; i++) | |||||
{ | |||||
var splittedValue = splitted[i]; | |||||
splittedValue = regEx.Replace(splittedValue, replacementValue).Replace(" ", replacementValue); | |||||
if (!string.IsNullOrEmpty(replacementValue)) | |||||
{ | |||||
while (splittedValue.Contains(doubleReplacementValue)) | |||||
{ | |||||
splittedValue = splittedValue.Replace(doubleReplacementValue, replacementValue); | |||||
} | |||||
} | |||||
splitted[i] = splittedValue.ToLower(); | |||||
} | |||||
finalValue = string.Join("/", splitted); | |||||
} | |||||
return finalValue; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,9 @@ | |||||
namespace Docnet | |||||
{ | |||||
public enum UrlFormatting | |||||
{ | |||||
None, | |||||
Strip, | |||||
Dashes | |||||
} | |||||
} |