@@ -225,6 +225,14 @@ namespace Docnet | |||
} | |||
} | |||
public bool StripIndexHtm | |||
{ | |||
get | |||
{ | |||
return _configData.StripIndexHtm ?? false; | |||
} | |||
} | |||
public string ThemeName | |||
{ | |||
get | |||
@@ -48,7 +48,8 @@ namespace Docnet | |||
var navigationContext = new NavigationContext | |||
{ | |||
MaxLevel = _loadedConfig.MaxLevelInToC, | |||
PathSpecification = _loadedConfig.PathSpecification | |||
PathSpecification = _loadedConfig.PathSpecification, | |||
StripIndexHtm = _loadedConfig.StripIndexHtm | |||
}; | |||
GeneratePages(navigationContext); | |||
@@ -78,7 +79,9 @@ namespace Docnet | |||
return null; | |||
} | |||
var indexElement = config.Pages.GetIndexElement(config.PathSpecification); | |||
var navigationContext = new NavigationContext(config.PathSpecification, config.MaxLevelInToC, config.StripIndexHtm); | |||
var indexElement = config.Pages.GetIndexElement(navigationContext); | |||
if(indexElement == null) | |||
{ | |||
Console.WriteLine("[ERROR] Root __index not found. The root navigationlevel is required to have an __index element"); | |||
@@ -55,11 +55,11 @@ namespace Docnet | |||
void CollectSearchIndexEntries(List<SearchIndexEntry> collectedEntries, NavigatedPath activePath, NavigationContext navigationContext); | |||
/// <summary> | |||
/// Gets the target URL with respect to the <see cref="PathSpecification"/>. | |||
/// Gets the target URL with respect to the <see cref="PathSpecification" />. | |||
/// </summary> | |||
/// <param name="pathSpecification">The path specification.</param> | |||
/// <param name="navigationContext">The navigation context.</param> | |||
/// <returns></returns> | |||
string GetTargetURL(PathSpecification pathSpecification); | |||
string GetTargetURL(NavigationContext navigationContext); | |||
/// <summary> | |||
/// Gets a value indicating whether this element is the __index element | |||
@@ -11,25 +11,23 @@ namespace Docnet | |||
/// Gets the final URL by encoding the path and by removing the filename if it equals <c>index.htm</c>. | |||
/// </summary> | |||
/// <param name="navigationElement">The navigation element.</param> | |||
/// <param name="pathSpecification">The path specification.</param> | |||
/// <param name="navigationContext">The navigation context.</param> | |||
/// <returns></returns> | |||
public static string GetFinalTargetUrl(this INavigationElement navigationElement, PathSpecification pathSpecification) | |||
public static string GetFinalTargetUrl(this INavigationElement navigationElement, NavigationContext navigationContext) | |||
{ | |||
var targetUrl = navigationElement.GetTargetURL(pathSpecification); | |||
var targetUrl = navigationElement.GetTargetURL(navigationContext); | |||
var link = HttpUtility.UrlPathEncode(targetUrl); | |||
// Disabled for now as discussed in #65 (https://github.com/FransBouma/DocNet/pull/65), but | |||
// is required for #44 | |||
//if (pathSpecification == PathSpecification.RelativeAsFolder) | |||
//{ | |||
// if (link.Length > IndexHtmFileName.Length && | |||
// link.EndsWith(IndexHtmFileName, StringComparison.InvariantCultureIgnoreCase)) | |||
// { | |||
// link = link.Substring(0, link.Length - IndexHtmFileName.Length); | |||
// } | |||
//} | |||
if (navigationContext.StripIndexHtm) | |||
{ | |||
if (link.Length > IndexHtmFileName.Length && | |||
link.EndsWith(IndexHtmFileName, StringComparison.InvariantCultureIgnoreCase)) | |||
{ | |||
link = link.Substring(0, link.Length - IndexHtmFileName.Length); | |||
} | |||
} | |||
return link; | |||
return link; | |||
} | |||
} | |||
} |
@@ -38,15 +38,15 @@ namespace Docnet | |||
/// Creates the bread crumbs HTML of the elements in this path, delimited by '/' characters. | |||
/// </summary> | |||
/// <param name="relativePathToRoot">The relative path back to the URL root, e.g. ../.., so it can be used for links to elements in this path.</param> | |||
/// <param name="pathSpecification">The path specification.</param> | |||
/// <param name="navigationContext">The navigation context.</param> | |||
/// <returns></returns> | |||
public string CreateBreadCrumbsHTML(string relativePathToRoot, PathSpecification pathSpecification) | |||
public string CreateBreadCrumbsHTML(string relativePathToRoot, NavigationContext navigationContext) | |||
{ | |||
var fragments = new List<string>(); | |||
// we enumerate a stack, which enumerates from top to bottom, so we have to reverse things first. | |||
foreach(var element in this.Reverse()) | |||
{ | |||
var targetURL = element.GetTargetURL(pathSpecification); | |||
var targetURL = element.GetTargetURL(navigationContext); | |||
if(string.IsNullOrWhiteSpace(targetURL)) | |||
{ | |||
fragments.Add(string.Format("<li>{0}</li>", element.Name)); | |||
@@ -7,15 +7,18 @@ | |||
MaxLevel = 2; | |||
} | |||
public NavigationContext(PathSpecification pathSpecification, int maxLevel) | |||
public NavigationContext(PathSpecification pathSpecification, int maxLevel, bool stripIndexHtm) | |||
: this() | |||
{ | |||
PathSpecification = pathSpecification; | |||
MaxLevel = maxLevel; | |||
StripIndexHtm = stripIndexHtm; | |||
} | |||
public PathSpecification PathSpecification { get; set; } | |||
public int MaxLevel { get; set; } | |||
public PathSpecification PathSpecification { get; set; } | |||
public bool StripIndexHtm { get; set; } | |||
} | |||
} |
@@ -55,11 +55,11 @@ namespace Docnet | |||
public abstract void CollectSearchIndexEntries(List<SearchIndexEntry> collectedEntries, NavigatedPath activePath, NavigationContext navigationContext); | |||
/// <summary> | |||
/// Gets the target URL with respect to the <see cref="PathSpecification"/>. | |||
/// Gets the target URL with respect to the <see cref="PathSpecification" />. | |||
/// </summary> | |||
/// <param name="pathSpecification">The path specification.</param> | |||
/// <param name="navigationContext">The navigation context.</param> | |||
/// <returns></returns> | |||
public abstract string GetTargetURL(PathSpecification pathSpecification); | |||
public abstract string GetTargetURL(NavigationContext navigationContext); | |||
#region Properties | |||
/// <summary> | |||
@@ -167,7 +167,7 @@ namespace Docnet | |||
// first render the level header, which is the index element, if present or a label. The root always has an __index element otherwise we'd have stopped at load. | |||
var elementStartTag = "<li><span class=\"navigationgroup\"><i class=\"fa fa-caret-down\"></i> "; | |||
var indexElement = this.GetIndexElement(navigationContext.PathSpecification); | |||
var indexElement = this.GetIndexElement(navigationContext); | |||
if (indexElement == null) | |||
{ | |||
fragments.Add(string.Format("{0}{1}</span></li>", elementStartTag, this.Name)); | |||
@@ -181,7 +181,7 @@ namespace Docnet | |||
else | |||
{ | |||
fragments.Add(string.Format("{0}<a href=\"{1}{2}\">{3}</a></span></li>", | |||
elementStartTag, relativePathToRoot, indexElement.GetFinalTargetUrl(navigationContext.PathSpecification), this.Name)); | |||
elementStartTag, relativePathToRoot, indexElement.GetFinalTargetUrl(navigationContext), this.Name)); | |||
} | |||
} | |||
// then the elements in the container. Index elements are skipped here. | |||
@@ -195,7 +195,7 @@ namespace Docnet | |||
{ | |||
// just a link | |||
fragments.Add(string.Format("<span class=\"navigationgroup\"><i class=\"fa fa-caret-right\"></i> <a href=\"{0}{1}\">{2}</a></span>", | |||
relativePathToRoot, this.GetFinalTargetUrl(navigationContext.PathSpecification), this.Name)); | |||
relativePathToRoot, this.GetFinalTargetUrl(navigationContext), this.Name)); | |||
} | |||
if (!this.IsRoot) | |||
{ | |||
@@ -277,18 +277,18 @@ namespace Docnet | |||
return title; | |||
} | |||
public override string GetTargetURL(PathSpecification pathSpecification) | |||
public override string GetTargetURL(NavigationContext navigationContext) | |||
{ | |||
var defaultElement = this.GetIndexElement(pathSpecification); | |||
var defaultElement = this.GetIndexElement(navigationContext); | |||
if (defaultElement == null) | |||
{ | |||
return string.Empty; | |||
} | |||
return defaultElement.GetTargetURL(pathSpecification) ?? string.Empty; | |||
return defaultElement.GetTargetURL(navigationContext) ?? string.Empty; | |||
} | |||
public SimpleNavigationElement GetIndexElement(PathSpecification pathSpecification) | |||
public SimpleNavigationElement GetIndexElement(NavigationContext navigationContext) | |||
{ | |||
var toReturn = this.Value.FirstOrDefault(e => e.IsIndexElement) as SimpleNavigationElement; | |||
if (toReturn == null) | |||
@@ -297,11 +297,11 @@ namespace Docnet | |||
var path = string.Empty; | |||
// Don't check parents when using relative paths since we need to walk the tree manually | |||
if (pathSpecification == PathSpecification.Full) | |||
if (navigationContext.PathSpecification == PathSpecification.Full) | |||
{ | |||
if (this.ParentContainer != null) | |||
{ | |||
path = Path.GetDirectoryName(this.ParentContainer.GetTargetURL(pathSpecification)); | |||
path = Path.GetDirectoryName(this.ParentContainer.GetTargetURL(navigationContext)); | |||
} | |||
} | |||
@@ -313,7 +313,7 @@ namespace Docnet | |||
var value = string.Format("{0}{1}.md", path, nameToUse); | |||
switch (pathSpecification) | |||
switch (navigationContext.PathSpecification) | |||
{ | |||
case PathSpecification.Full: | |||
// Default is correct | |||
@@ -342,7 +342,7 @@ namespace Docnet | |||
var firstChildNavigationLevel = (NavigationLevel)this.Value.FirstOrDefault(x => x is NavigationLevel && ((NavigationLevel)x).Value.Any() && !ReferenceEquals(this, x)); | |||
if (firstChildNavigationLevel != null) | |||
{ | |||
var targetUrl = firstChildNavigationLevel.Value.First().GetTargetURL(pathSpecification); | |||
var targetUrl = firstChildNavigationLevel.Value.First().GetTargetURL(navigationContext); | |||
// 3 times since we need 2 parents up | |||
preferredPath = Path.GetDirectoryName(targetUrl); | |||
@@ -359,7 +359,7 @@ namespace Docnet | |||
break; | |||
default: | |||
throw new ArgumentOutOfRangeException(nameof(pathSpecification), pathSpecification, null); | |||
throw new ArgumentOutOfRangeException(nameof(navigationContext.PathSpecification), navigationContext.PathSpecification, null); | |||
} | |||
toReturn = new SimpleNavigationElement | |||
@@ -62,7 +62,7 @@ namespace Docnet | |||
} | |||
_relativeLinksOnPage.Clear(); | |||
var sourceFile = Utils.MakeAbsolutePath(activeConfig.Source, this.Value); | |||
var destinationFile = Utils.MakeAbsolutePath(activeConfig.Destination, this.GetTargetURL(navigationContext.PathSpecification)); | |||
var destinationFile = Utils.MakeAbsolutePath(activeConfig.Destination, this.GetTargetURL(navigationContext)); | |||
var sb = new StringBuilder(activeConfig.PageTemplateContents.Length + 2048); | |||
var content = string.Empty; | |||
this.MarkdownFromFile = string.Empty; | |||
@@ -92,7 +92,7 @@ namespace Docnet | |||
continue; | |||
} | |||
defaultMarkdown.AppendFormat("* [{0}]({1}{2}){3}", sibling.Name, relativePathToRoot, | |||
sibling.GetFinalTargetUrl(navigationContext.PathSpecification), Environment.NewLine); | |||
sibling.GetFinalTargetUrl(navigationContext), Environment.NewLine); | |||
} | |||
defaultMarkdown.Append(Environment.NewLine); | |||
content = Utils.ConvertMarkdownToHtml(defaultMarkdown.ToString(), Path.GetDirectoryName(destinationFile), activeConfig.Destination, string.Empty, _relativeLinksOnPage, activeConfig.ConvertLocalLinks); | |||
@@ -114,7 +114,7 @@ namespace Docnet | |||
sb.Replace("{{Path}}", relativePathToRoot); | |||
sb.Replace("{{RelativeSourceFileName}}", Utils.MakeRelativePathForUri(activeConfig.Destination, sourceFile).TrimEnd('/')); | |||
sb.Replace("{{RelativeTargetFileName}}", Utils.MakeRelativePathForUri(activeConfig.Destination, destinationFile).TrimEnd('/')); | |||
sb.Replace("{{Breadcrumbs}}", activePath.CreateBreadCrumbsHTML(relativePathToRoot, navigationContext.PathSpecification)); | |||
sb.Replace("{{Breadcrumbs}}", activePath.CreateBreadCrumbsHTML(relativePathToRoot, navigationContext)); | |||
sb.Replace("{{ToC}}", activePath.CreateToCHTML(relativePathToRoot, navigationContext)); | |||
sb.Replace("{{ExtraScript}}", (this.ExtraScriptProducerFunc == null) ? string.Empty : this.ExtraScriptProducerFunc(this)); | |||
@@ -142,7 +142,7 @@ namespace Docnet | |||
if (!this.IsIndexElement) | |||
{ | |||
var toAdd = new SearchIndexEntry(); | |||
toAdd.Fill(this.MarkdownFromFile, this.GetTargetURL(navigationContext.PathSpecification), this.Name, activePath); | |||
toAdd.Fill(this.MarkdownFromFile, this.GetTargetURL(navigationContext), this.Name, activePath); | |||
collectedEntries.Add(toAdd); | |||
} | |||
activePath.Pop(); | |||
@@ -192,7 +192,7 @@ namespace Docnet | |||
string.IsNullOrWhiteSpace(liClass) ? string.Empty : string.Format(" class=\"{0}\"", liClass), | |||
string.IsNullOrWhiteSpace(aClass) ? string.Empty : string.Format(" class=\"{0}\"", aClass), | |||
relativePathToRoot, | |||
this.GetFinalTargetUrl(navigationContext.PathSpecification), | |||
this.GetFinalTargetUrl(navigationContext), | |||
this.Name)); | |||
if (isCurrent && _relativeLinksOnPage.SelectMany(x => x.Children).Any(x => x.Level > 1)) | |||
{ | |||
@@ -220,10 +220,9 @@ namespace Docnet | |||
/// <summary> | |||
/// Gets the target URL with respect to the <see cref="T:Docnet.PathSpecification" />. | |||
/// </summary> | |||
/// <param name="pathSpecification">The path specification.</param> | |||
/// <param name="navigationContext">The navigation context.</param> | |||
/// <returns></returns> | |||
/// <exception cref="System.NotImplementedException"></exception> | |||
public override string GetTargetURL(PathSpecification pathSpecification) | |||
public override string GetTargetURL(NavigationContext navigationContext) | |||
{ | |||
if (_targetURLForHTML == null) | |||
{ | |||
@@ -232,7 +231,7 @@ namespace Docnet | |||
var toReplace = ".md"; | |||
var replacement = ".htm"; | |||
if (pathSpecification == PathSpecification.RelativeAsFolder) | |||
if (navigationContext.PathSpecification == PathSpecification.RelativeAsFolder) | |||
{ | |||
if (!IsIndexElement && !_targetURLForHTML.EndsWith("index.md", StringComparison.InvariantCultureIgnoreCase)) | |||
{ | |||