@@ -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() | internal void ClearDestinationFolder() | ||||
{ | { | ||||
if(string.IsNullOrWhiteSpace(this.Destination)) | if(string.IsNullOrWhiteSpace(this.Destination)) | ||||
@@ -151,7 +166,7 @@ namespace Docnet | |||||
var activePath = new NavigatedPath(); | var activePath = new NavigatedPath(); | ||||
activePath.Push(this.Pages); | activePath.Push(this.Pages); | ||||
var searchSimpleElement = new SimpleNavigationElement() {Name = "Search", Value = "Docnet_search.htm", IsIndexElement = false, ParentContainer = 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> | <h1 id=""search"">Search Results</h1> | ||||
<p> | <p> | ||||
<form id=""content_search"" action=""docnet_search.htm""> | <form id=""content_search"" action=""docnet_search.htm""> | ||||
@@ -162,7 +177,7 @@ namespace Docnet | |||||
<div id=""search-results""> | <div id=""search-results""> | ||||
<p>Sorry, page not found.</p> | <p>Sorry, page not found.</p> | ||||
</div>"; | </div>"; | ||||
searchSimpleElement.ExtraScriptProducerFunc = e=> @" | |||||
searchSimpleElement.ExtraScriptProducerFunc = (e,c,n) => @" | |||||
<script>var base_url = '.';</script> | <script>var base_url = '.';</script> | ||||
<script data-main=""js/search.js"" src=""js/require.js""></script>"; | <script data-main=""js/search.js"" src=""js/require.js""></script>"; | ||||
searchSimpleElement.GenerateOutput(this, activePath, navigationContext); | searchSimpleElement.GenerateOutput(this, activePath, navigationContext); | ||||
@@ -61,6 +61,7 @@ | |||||
<Compile Include="NavigationContext.cs" /> | <Compile Include="NavigationContext.cs" /> | ||||
<Compile Include="NavigationElement.cs" /> | <Compile Include="NavigationElement.cs" /> | ||||
<Compile Include="NavigationLevel.cs" /> | <Compile Include="NavigationLevel.cs" /> | ||||
<Compile Include="NotFoundNavigationElement.cs" /> | |||||
<Compile Include="PathSpecification.cs" /> | <Compile Include="PathSpecification.cs" /> | ||||
<Compile Include="Program.cs" /> | <Compile Include="Program.cs" /> | ||||
<Compile Include="Properties\AssemblyInfo.cs" /> | <Compile Include="Properties\AssemblyInfo.cs" /> | ||||
@@ -106,6 +106,8 @@ namespace Docnet | |||||
_loadedConfig.CopySourceFoldersToCopy(); | _loadedConfig.CopySourceFoldersToCopy(); | ||||
Console.WriteLine("Generating pages in '{0}'", _loadedConfig.Destination); | Console.WriteLine("Generating pages in '{0}'", _loadedConfig.Destination); | ||||
_loadedConfig.Pages.GenerateOutput(_loadedConfig, new NavigatedPath(), navigationContext); | _loadedConfig.Pages.GenerateOutput(_loadedConfig, new NavigatedPath(), navigationContext); | ||||
Console.WriteLine("Generating 404 page"); | |||||
_loadedConfig.Generate404Page(navigationContext); | |||||
Console.WriteLine("Generating search index"); | Console.WriteLine("Generating search index"); | ||||
_loadedConfig.GenerateSearchData(navigationContext); | _loadedConfig.GenerateSearchData(navigationContext); | ||||
Console.WriteLine("Done!"); | 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)); | 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); | sb.Append(activeConfig.PageTemplateContents); | ||||
@@ -116,7 +116,7 @@ namespace Docnet | |||||
sb.Replace("{{RelativeTargetFileName}}", Utils.MakeRelativePathForUri(activeConfig.Destination, destinationFile).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.PathSpecification)); | ||||
sb.Replace("{{ToC}}", activePath.CreateToCHTML(relativePathToRoot, navigationContext)); | 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 | // 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); | 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. | /// 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. | /// Use this to produce in-line HTML for specific pages which aren't specified, like the search page. | ||||
/// </summary> | /// </summary> | ||||
public Func<SimpleNavigationElement, string> ContentProducerFunc { get; set; } | |||||
public Func<SimpleNavigationElement, Config, NavigationContext, string> ContentProducerFunc { get; set; } | |||||
/// <summary> | /// <summary> | ||||
/// Gets or sets the extra script producer function, which, if set, produces HTML to be embedded at the extra script marker | /// Gets or sets the extra script producer function, which, if set, produces HTML to be embedded at the extra script marker | ||||
/// </summary> | /// </summary> | ||||
public Func<SimpleNavigationElement, string> ExtraScriptProducerFunc { get; set; } | |||||
public Func<SimpleNavigationElement, Config, NavigationContext, string> ExtraScriptProducerFunc { get; set; } | |||||
/// <summary> | /// <summary> | ||||
/// Gets the loaded markdown text from the file. | /// Gets the loaded markdown text from the file. | ||||
@@ -316,7 +316,7 @@ namespace Docnet | |||||
public string MarkdownFromFile | public string MarkdownFromFile | ||||
{ | { | ||||
get; | get; | ||||
private set; | |||||
protected set; | |||||
} | } | ||||
#endregion | #endregion | ||||
} | } | ||||