@@ -110,6 +110,21 @@ namespace Docnet | |||
} | |||
} | |||
internal void Generate404Page(NavigationContext navigationContext) | |||
{ | |||
var simpleNavigationElement = new NotFoundNavigationElement | |||
{ | |||
ParentContainer = Pages | |||
}; | |||
var navigatedPath = new NavigatedPath(); | |||
navigatedPath.Push(this.Pages); | |||
simpleNavigationElement.GenerateOutput(this, navigatedPath, navigationContext); | |||
navigatedPath.Pop(); | |||
} | |||
internal void ClearDestinationFolder() | |||
{ | |||
if(string.IsNullOrWhiteSpace(this.Destination)) | |||
@@ -151,7 +166,7 @@ namespace Docnet | |||
var activePath = new NavigatedPath(); | |||
activePath.Push(this.Pages); | |||
var searchSimpleElement = new SimpleNavigationElement() {Name = "Search", Value = "Docnet_search.htm", IsIndexElement = false, ParentContainer = this.Pages}; | |||
searchSimpleElement.ContentProducerFunc = e=>@" | |||
searchSimpleElement.ContentProducerFunc = (e,c,n) =>@" | |||
<h1 id=""search"">Search Results</h1> | |||
<p> | |||
<form id=""content_search"" action=""docnet_search.htm""> | |||
@@ -162,7 +177,7 @@ namespace Docnet | |||
<div id=""search-results""> | |||
<p>Sorry, page not found.</p> | |||
</div>"; | |||
searchSimpleElement.ExtraScriptProducerFunc = e=> @" | |||
searchSimpleElement.ExtraScriptProducerFunc = (e,c,n) => @" | |||
<script>var base_url = '.';</script> | |||
<script data-main=""js/search.js"" src=""js/require.js""></script>"; | |||
searchSimpleElement.GenerateOutput(this, activePath, navigationContext); | |||
@@ -61,6 +61,7 @@ | |||
<Compile Include="NavigationContext.cs" /> | |||
<Compile Include="NavigationElement.cs" /> | |||
<Compile Include="NavigationLevel.cs" /> | |||
<Compile Include="NotFoundNavigationElement.cs" /> | |||
<Compile Include="PathSpecification.cs" /> | |||
<Compile Include="Program.cs" /> | |||
<Compile Include="Properties\AssemblyInfo.cs" /> | |||
@@ -106,6 +106,8 @@ namespace Docnet | |||
_loadedConfig.CopySourceFoldersToCopy(); | |||
Console.WriteLine("Generating pages in '{0}'", _loadedConfig.Destination); | |||
_loadedConfig.Pages.GenerateOutput(_loadedConfig, new NavigatedPath(), navigationContext); | |||
Console.WriteLine("Generating 404 page"); | |||
_loadedConfig.Generate404Page(navigationContext); | |||
Console.WriteLine("Generating search index"); | |||
_loadedConfig.GenerateSearchData(navigationContext); | |||
Console.WriteLine("Done!"); | |||
@@ -0,0 +1,67 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.IO; | |||
using System.Text; | |||
using MarkdownDeep; | |||
namespace Docnet | |||
{ | |||
public class NotFoundNavigationElement : SimpleNavigationElement | |||
{ | |||
public NotFoundNavigationElement() | |||
{ | |||
this.Name = "Page not found"; | |||
this.IsIndexElement = false; | |||
this.ContentProducerFunc = GenerateContent; | |||
} | |||
private string GenerateContent(SimpleNavigationElement element, Config config, NavigationContext navigationContext) | |||
{ | |||
var stringBuilder = new StringBuilder(); | |||
stringBuilder.AppendLine("# Page not found (404)"); | |||
stringBuilder.AppendLine(); | |||
stringBuilder.AppendLine("Unfortunately the page you were looking for does not exist. In order to help you out "); | |||
stringBuilder.AppendLine("in the best way possible, below is the table of contents:"); | |||
stringBuilder.AppendLine(); | |||
foreach (var sibling in this.ParentContainer.Value) | |||
{ | |||
if (sibling == this) | |||
{ | |||
continue; | |||
} | |||
stringBuilder.AppendFormat("* [{0}]({1}{2}){3}", sibling.Name, "/" /* pathRelativeToRoot */, | |||
sibling.GetFinalTargetUrl(navigationContext.PathSpecification), Environment.NewLine); | |||
} | |||
var markdownContent = stringBuilder.ToString(); | |||
var destinationFile = Utils.MakeAbsolutePath(config.Destination, this.GetTargetURL(navigationContext.PathSpecification)); | |||
var htmlContent = Utils.ConvertMarkdownToHtml(markdownContent, Path.GetDirectoryName(destinationFile), config.Destination, | |||
string.Empty, new List<Heading>(), config.ConvertLocalLinks); | |||
return htmlContent; | |||
} | |||
public override string GenerateToCFragment(NavigatedPath navigatedPath, string relativePathToRoot, NavigationContext navigationContext) | |||
{ | |||
// Skip | |||
return string.Empty; | |||
} | |||
public override void CollectSearchIndexEntries(List<SearchIndexEntry> collectedEntries, NavigatedPath activePath, NavigationContext navigationContext) | |||
{ | |||
// Skip | |||
} | |||
public override string GetTargetURL(PathSpecification pathSpecification) | |||
{ | |||
return "404.htm"; | |||
} | |||
public override bool IsIndexElement { get; set; } | |||
} | |||
} |
@@ -104,7 +104,7 @@ namespace Docnet | |||
{ | |||
throw new FileNotFoundException(string.Format("The specified markdown file '{0}' couldn't be found. Aborting", sourceFile)); | |||
} | |||
content = this.ContentProducerFunc(this); | |||
content = this.ContentProducerFunc(this, activeConfig, navigationContext); | |||
} | |||
} | |||
sb.Append(activeConfig.PageTemplateContents); | |||
@@ -116,7 +116,7 @@ namespace Docnet | |||
sb.Replace("{{RelativeTargetFileName}}", Utils.MakeRelativePathForUri(activeConfig.Destination, destinationFile).TrimEnd('/')); | |||
sb.Replace("{{Breadcrumbs}}", activePath.CreateBreadCrumbsHTML(relativePathToRoot, navigationContext.PathSpecification)); | |||
sb.Replace("{{ToC}}", activePath.CreateToCHTML(relativePathToRoot, navigationContext)); | |||
sb.Replace("{{ExtraScript}}", (this.ExtraScriptProducerFunc == null) ? string.Empty : this.ExtraScriptProducerFunc(this)); | |||
sb.Replace("{{ExtraScript}}", (this.ExtraScriptProducerFunc == null) ? string.Empty : this.ExtraScriptProducerFunc(this, activeConfig, navigationContext)); | |||
// the last action has to be replacing the content marker, so markers in the content which we have in the template as well aren't replaced | |||
sb.Replace("{{Content}}", content); | |||
@@ -304,11 +304,11 @@ namespace Docnet | |||
/// If null, and the target file isn't found, the engine will throw an error as there's no content. If set, it's utilized over the default markdown producer. | |||
/// Use this to produce in-line HTML for specific pages which aren't specified, like the search page. | |||
/// </summary> | |||
public Func<SimpleNavigationElement, string> ContentProducerFunc { get; set; } | |||
public Func<SimpleNavigationElement, Config, NavigationContext, string> ContentProducerFunc { get; set; } | |||
/// <summary> | |||
/// Gets or sets the extra script producer function, which, if set, produces HTML to be embedded at the extra script marker | |||
/// </summary> | |||
public Func<SimpleNavigationElement, string> ExtraScriptProducerFunc { get; set; } | |||
public Func<SimpleNavigationElement, Config, NavigationContext, string> ExtraScriptProducerFunc { get; set; } | |||
/// <summary> | |||
/// Gets the loaded markdown text from the file. | |||
@@ -316,7 +316,7 @@ namespace Docnet | |||
public string MarkdownFromFile | |||
{ | |||
get; | |||
private set; | |||
protected set; | |||
} | |||
#endregion | |||
} | |||