@@ -72,10 +72,11 @@ namespace Docnet | |||
/// Generates the search data, which is the json file called 'search_index.json' with search data of all pages as well as the docnet_search.htm file in the output. | |||
/// The search index is written to the root of the output folder. | |||
/// </summary> | |||
internal void GenerateSearchData() | |||
/// <param name="navigationContext">The navigation context.</param> | |||
internal void GenerateSearchData(NavigationContext navigationContext) | |||
{ | |||
GenerateSearchPage(); | |||
GenerateSearchDataIndex(); | |||
GenerateSearchPage(navigationContext); | |||
GenerateSearchDataIndex(navigationContext); | |||
} | |||
internal void CopyThemeToDestination() | |||
@@ -128,10 +129,10 @@ namespace Docnet | |||
/// <summary> | |||
/// Generates the index of the search data. this is a json file with per page which has markdown a couple of data elements. | |||
/// </summary> | |||
private void GenerateSearchDataIndex() | |||
private void GenerateSearchDataIndex(NavigationContext navigationContext) | |||
{ | |||
var collectedSearchEntries = new List<SearchIndexEntry>(); | |||
this.Pages.CollectSearchIndexEntries(collectedSearchEntries, new NavigatedPath(), this.PathSpecification); | |||
this.Pages.CollectSearchIndexEntries(collectedSearchEntries, new NavigatedPath(), navigationContext); | |||
JObject searchIndex = new JObject(new JProperty("docs", | |||
new JArray( | |||
collectedSearchEntries.Select(e=>new JObject( | |||
@@ -145,7 +146,7 @@ namespace Docnet | |||
} | |||
private void GenerateSearchPage() | |||
private void GenerateSearchPage(NavigationContext navigationContext) | |||
{ | |||
var activePath = new NavigatedPath(); | |||
activePath.Push(this.Pages); | |||
@@ -164,7 +165,7 @@ namespace Docnet | |||
searchSimpleElement.ExtraScriptProducerFunc = e=> @" | |||
<script>var base_url = '.';</script> | |||
<script data-main=""js/search.js"" src=""js/require.js""></script>"; | |||
searchSimpleElement.GenerateOutput(this, activePath, this.PathSpecification); | |||
searchSimpleElement.GenerateOutput(this, activePath, navigationContext); | |||
activePath.Pop(); | |||
} | |||
@@ -58,6 +58,7 @@ | |||
<Compile Include="Engine.cs" /> | |||
<Compile Include="INavigationElement.cs" /> | |||
<Compile Include="NavigatedPath.cs" /> | |||
<Compile Include="NavigationContext.cs" /> | |||
<Compile Include="NavigationElement.cs" /> | |||
<Compile Include="NavigationLevel.cs" /> | |||
<Compile Include="PathSpecification.cs" /> | |||
@@ -44,7 +44,14 @@ namespace Docnet | |||
{ | |||
return 1; | |||
} | |||
GeneratePages(); | |||
var navigationContext = new NavigationContext | |||
{ | |||
MaxLevel = _loadedConfig.MaxLevelInToC, | |||
PathSpecification = _loadedConfig.PathSpecification | |||
}; | |||
GeneratePages(navigationContext); | |||
return 0; | |||
} | |||
@@ -86,7 +93,7 @@ namespace Docnet | |||
/// Generates the pages from the md files in the source, using the page template loaded and the loaded config. | |||
/// </summary> | |||
/// <returns>true if everything went ok, false otherwise</returns> | |||
private void GeneratePages() | |||
private void GeneratePages(NavigationContext navigationContext) | |||
{ | |||
if(_input.ClearDestinationFolder) | |||
{ | |||
@@ -98,9 +105,9 @@ namespace Docnet | |||
Console.WriteLine("Copying source folders to copy."); | |||
_loadedConfig.CopySourceFoldersToCopy(); | |||
Console.WriteLine("Generating pages in '{0}'", _loadedConfig.Destination); | |||
_loadedConfig.Pages.GenerateOutput(_loadedConfig, new NavigatedPath(), _loadedConfig.PathSpecification); | |||
_loadedConfig.Pages.GenerateOutput(_loadedConfig, new NavigatedPath(), navigationContext); | |||
Console.WriteLine("Generating search index"); | |||
_loadedConfig.GenerateSearchData(); | |||
_loadedConfig.GenerateSearchData(navigationContext); | |||
Console.WriteLine("Done!"); | |||
} | |||
} |
@@ -35,24 +35,24 @@ namespace Docnet | |||
/// </summary> | |||
/// <param name="activeConfig">The active configuration to use for the output.</param> | |||
/// <param name="activePath">The active path navigated through the ToC to reach this element.</param> | |||
/// <param name="pathSpecification">The path specification.</param> | |||
void GenerateOutput(Config activeConfig, NavigatedPath activePath, PathSpecification pathSpecification); | |||
/// <param name="navigationContext">The navigation context.</param> | |||
void GenerateOutput(Config activeConfig, NavigatedPath activePath, NavigationContext navigationContext); | |||
/// <summary> | |||
/// Generates the ToC fragment for this element, which can either be a simple line or a full expanded menu. | |||
/// </summary> | |||
/// <param name="navigatedPath">The navigated path to the current element, which doesn't necessarily have to be this element.</param> | |||
/// <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> | |||
string GenerateToCFragment(NavigatedPath navigatedPath, string relativePathToRoot, PathSpecification pathSpecification); | |||
string GenerateToCFragment(NavigatedPath navigatedPath, string relativePathToRoot, NavigationContext navigationContext); | |||
/// <summary> | |||
/// Collects the search index entries. These are created from simple navigation elements found in this container, which aren't index element. | |||
/// </summary> | |||
/// <param name="collectedEntries">The collected entries.</param> | |||
/// <param name="activePath">The active path currently navigated.</param> | |||
/// <param name="pathSpecification">The path specification.</param> | |||
void CollectSearchIndexEntries(List<SearchIndexEntry> collectedEntries, NavigatedPath activePath, PathSpecification pathSpecification); | |||
/// <param name="navigationContext">The navigation context.</param> | |||
void CollectSearchIndexEntries(List<SearchIndexEntry> collectedEntries, NavigatedPath activePath, NavigationContext navigationContext); | |||
/// <summary> | |||
/// Gets the target URL with respect to the <see cref="PathSpecification"/>. | |||
@@ -77,9 +77,9 @@ namespace Docnet | |||
/// aren't, are not expanded. | |||
/// </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 CreateToCHTML(string relativePathToRoot, PathSpecification pathSpecification) | |||
public string CreateToCHTML(string relativePathToRoot, NavigationContext navigationContext) | |||
{ | |||
// the root container is the bottom element of this path. We use that container to build the root and navigate any node open along the navigated path. | |||
var rootContainer = this.Reverse().FirstOrDefault() as NavigationLevel; | |||
@@ -88,7 +88,7 @@ namespace Docnet | |||
// no root container, no TOC | |||
return string.Empty; | |||
} | |||
return rootContainer.GenerateToCFragment(this, relativePathToRoot, pathSpecification); | |||
return rootContainer.GenerateToCFragment(this, relativePathToRoot, navigationContext); | |||
} | |||
} | |||
} |
@@ -0,0 +1,21 @@ | |||
namespace Docnet | |||
{ | |||
public class NavigationContext | |||
{ | |||
public NavigationContext() | |||
{ | |||
MaxLevel = 2; | |||
} | |||
public NavigationContext(PathSpecification pathSpecification, int maxLevel) | |||
: this() | |||
{ | |||
PathSpecification = pathSpecification; | |||
MaxLevel = maxLevel; | |||
} | |||
public int MaxLevel { get; set; } | |||
public PathSpecification PathSpecification { get; set; } | |||
} | |||
} |
@@ -36,23 +36,23 @@ namespace Docnet | |||
/// </summary> | |||
/// <param name="activeConfig">The active configuration to use for the output.</param> | |||
/// <param name="activePath">The active path navigated through the ToC to reach this element.</param> | |||
/// <param name="pathSpecification">The path specification.</param> | |||
public abstract void GenerateOutput(Config activeConfig, NavigatedPath activePath, PathSpecification pathSpecification); | |||
/// <param name="navigationContext">The navigation context.</param> | |||
public abstract void GenerateOutput(Config activeConfig, NavigatedPath activePath, NavigationContext navigationContext); | |||
/// <summary> | |||
/// Generates the ToC fragment for this element, which can either be a simple line or a full expanded menu. | |||
/// </summary> | |||
/// <param name="navigatedPath">The navigated path to the current element, which doesn't necessarily have to be this element.</param> | |||
/// <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 abstract string GenerateToCFragment(NavigatedPath navigatedPath, string relativePathToRoot, PathSpecification pathSpecification); | |||
public abstract string GenerateToCFragment(NavigatedPath navigatedPath, string relativePathToRoot, NavigationContext navigationContext); | |||
/// <summary> | |||
/// Collects the search index entries. These are created from simple navigation elements found in this container, which aren't index element. | |||
/// </summary> | |||
/// <param name="collectedEntries">The collected entries.</param> | |||
/// <param name="activePath">The active path currently navigated.</param> | |||
/// <param name="pathSpecification">The path specification.</param> | |||
public abstract void CollectSearchIndexEntries(List<SearchIndexEntry> collectedEntries, NavigatedPath activePath, PathSpecification pathSpecification); | |||
/// <param name="navigationContext">The navigation context.</param> | |||
public abstract void CollectSearchIndexEntries(List<SearchIndexEntry> collectedEntries, NavigatedPath activePath, NavigationContext navigationContext); | |||
/// <summary> | |||
/// Gets the target URL with respect to the <see cref="PathSpecification"/>. | |||
@@ -106,13 +106,13 @@ namespace Docnet | |||
/// </summary> | |||
/// <param name="collectedEntries">The collected entries.</param> | |||
/// <param name="activePath">The active path currently navigated.</param> | |||
/// <param name="pathSpecification">The path specification.</param> | |||
public override void CollectSearchIndexEntries(List<SearchIndexEntry> collectedEntries, NavigatedPath activePath, PathSpecification pathSpecification) | |||
/// <param name="navigationContext">The navigation context.</param> | |||
public override void CollectSearchIndexEntries(List<SearchIndexEntry> collectedEntries, NavigatedPath activePath, NavigationContext navigationContext) | |||
{ | |||
activePath.Push(this); | |||
foreach (var element in this.Value) | |||
{ | |||
element.CollectSearchIndexEntries(collectedEntries, activePath, pathSpecification); | |||
element.CollectSearchIndexEntries(collectedEntries, activePath, navigationContext); | |||
} | |||
activePath.Pop(); | |||
} | |||
@@ -123,15 +123,15 @@ namespace Docnet | |||
/// </summary> | |||
/// <param name="activeConfig">The active configuration to use for the output.</param> | |||
/// <param name="activePath">The active path navigated through the ToC to reach this element.</param> | |||
/// <param name="pathSpecification">The path specification.</param> | |||
public override void GenerateOutput(Config activeConfig, NavigatedPath activePath, PathSpecification pathSpecification) | |||
/// <param name="navigationContext">The navigation context.</param> | |||
public override void GenerateOutput(Config activeConfig, NavigatedPath activePath, NavigationContext navigationContext) | |||
{ | |||
activePath.Push(this); | |||
int i = 0; | |||
while (i < this.Value.Count) | |||
{ | |||
var element = this.Value[i]; | |||
element.GenerateOutput(activeConfig, activePath, pathSpecification); | |||
element.GenerateOutput(activeConfig, activePath, navigationContext); | |||
i++; | |||
} | |||
activePath.Pop(); | |||
@@ -143,9 +143,9 @@ namespace Docnet | |||
/// </summary> | |||
/// <param name="navigatedPath">The navigated path to the current element, which doesn't necessarily have to be this element.</param> | |||
/// <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 override string GenerateToCFragment(NavigatedPath navigatedPath, string relativePathToRoot, PathSpecification pathSpecification) | |||
public override string GenerateToCFragment(NavigatedPath navigatedPath, string relativePathToRoot, NavigationContext navigationContext) | |||
{ | |||
var fragments = new List<string>(); | |||
if (!this.IsRoot) | |||
@@ -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(pathSpecification); | |||
var indexElement = this.GetIndexElement(navigationContext.PathSpecification); | |||
if (indexElement == null) | |||
{ | |||
fragments.Add(string.Format("{0}{1}</span></li>", elementStartTag, this.Name)); | |||
@@ -176,18 +176,18 @@ namespace Docnet | |||
{ | |||
if (this.IsRoot) | |||
{ | |||
fragments.Add(indexElement.PerformGenerateToCFragment(navigatedPath, relativePathToRoot, pathSpecification)); | |||
fragments.Add(indexElement.PerformGenerateToCFragment(navigatedPath, relativePathToRoot, navigationContext)); | |||
} | |||
else | |||
{ | |||
fragments.Add(string.Format("{0}<a href=\"{1}{2}\">{3}</a></span></li>", | |||
elementStartTag, relativePathToRoot, indexElement.GetFinalTargetUrl(pathSpecification), this.Name)); | |||
elementStartTag, relativePathToRoot, indexElement.GetFinalTargetUrl(navigationContext.PathSpecification), this.Name)); | |||
} | |||
} | |||
// then the elements in the container. Index elements are skipped here. | |||
foreach (var element in this.Value) | |||
{ | |||
fragments.Add(element.GenerateToCFragment(navigatedPath, relativePathToRoot, pathSpecification)); | |||
fragments.Add(element.GenerateToCFragment(navigatedPath, relativePathToRoot, navigationContext)); | |||
} | |||
fragments.Add("</ul>"); | |||
} | |||
@@ -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(pathSpecification), this.Name)); | |||
relativePathToRoot, this.GetFinalTargetUrl(navigationContext.PathSpecification), this.Name)); | |||
} | |||
if (!this.IsRoot) | |||
{ | |||
@@ -27,6 +27,7 @@ using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using System.Web; | |||
using MarkdownDeep; | |||
namespace Docnet | |||
{ | |||
@@ -34,13 +35,13 @@ namespace Docnet | |||
{ | |||
#region Members | |||
private string _targetURLForHTML; | |||
private List<Tuple<string, string>> _relativeH2LinksOnPage; // first element in Tuple is anchor name, second is name for ToC. | |||
private readonly List<Heading> _relativeLinksOnPage; | |||
#endregion | |||
public SimpleNavigationElement() | |||
{ | |||
_relativeH2LinksOnPage = new List<Tuple<string, string>>(); | |||
_relativeLinksOnPage = new List<Heading>(); | |||
} | |||
@@ -49,18 +50,19 @@ namespace Docnet | |||
/// </summary> | |||
/// <param name="activeConfig">The active configuration to use for the output.</param> | |||
/// <param name="activePath">The active path navigated through the ToC to reach this element.</param> | |||
/// <param name="pathSpecification">The path specification.</param> | |||
/// <param name="navigationContext">The navigation context.</param> | |||
/// <exception cref="FileNotFoundException"></exception> | |||
/// <exception cref="System.IO.FileNotFoundException"></exception> | |||
public override void GenerateOutput(Config activeConfig, NavigatedPath activePath, PathSpecification pathSpecification) | |||
public override void GenerateOutput(Config activeConfig, NavigatedPath activePath, NavigationContext navigationContext) | |||
{ | |||
// if we're the __index element, we're not pushing ourselves on the path, as we're representing the container we're in, which is already on the path. | |||
if(!this.IsIndexElement) | |||
{ | |||
activePath.Push(this); | |||
} | |||
_relativeH2LinksOnPage.Clear(); | |||
_relativeLinksOnPage.Clear(); | |||
var sourceFile = Utils.MakeAbsolutePath(activeConfig.Source, this.Value); | |||
var destinationFile = Utils.MakeAbsolutePath(activeConfig.Destination, this.GetTargetURL(pathSpecification)); | |||
var destinationFile = Utils.MakeAbsolutePath(activeConfig.Destination, this.GetTargetURL(navigationContext.PathSpecification)); | |||
var sb = new StringBuilder(activeConfig.PageTemplateContents.Length + 2048); | |||
var content = string.Empty; | |||
this.MarkdownFromFile = string.Empty; | |||
@@ -70,7 +72,7 @@ namespace Docnet | |||
this.MarkdownFromFile = File.ReadAllText(sourceFile, Encoding.UTF8); | |||
// Check if the content contains @@include tag | |||
content = Utils.IncludeProcessor(this.MarkdownFromFile, Utils.MakeAbsolutePath(activeConfig.Source, activeConfig.IncludeFolder)); | |||
content = Utils.ConvertMarkdownToHtml(content, Path.GetDirectoryName(destinationFile), activeConfig.Destination, sourceFile, _relativeH2LinksOnPage, activeConfig.ConvertLocalLinks); | |||
content = Utils.ConvertMarkdownToHtml(content, Path.GetDirectoryName(destinationFile), activeConfig.Destination, sourceFile, _relativeLinksOnPage, activeConfig.ConvertLocalLinks); | |||
} | |||
else | |||
{ | |||
@@ -90,10 +92,10 @@ namespace Docnet | |||
continue; | |||
} | |||
defaultMarkdown.AppendFormat("* [{0}]({1}{2}){3}", sibling.Name, relativePathToRoot, | |||
sibling.GetFinalTargetUrl(pathSpecification), Environment.NewLine); | |||
sibling.GetFinalTargetUrl(navigationContext.PathSpecification), Environment.NewLine); | |||
} | |||
defaultMarkdown.Append(Environment.NewLine); | |||
content = Utils.ConvertMarkdownToHtml(defaultMarkdown.ToString(), Path.GetDirectoryName(destinationFile), activeConfig.Destination, string.Empty, _relativeH2LinksOnPage, activeConfig.ConvertLocalLinks); | |||
content = Utils.ConvertMarkdownToHtml(defaultMarkdown.ToString(), Path.GetDirectoryName(destinationFile), activeConfig.Destination, string.Empty, _relativeLinksOnPage, activeConfig.ConvertLocalLinks); | |||
} | |||
else | |||
{ | |||
@@ -112,8 +114,8 @@ 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, pathSpecification)); | |||
sb.Replace("{{ToC}}", activePath.CreateToCHTML(relativePathToRoot, pathSpecification)); | |||
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)); | |||
// 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 | |||
@@ -132,15 +134,15 @@ namespace Docnet | |||
/// </summary> | |||
/// <param name="collectedEntries">The collected entries.</param> | |||
/// <param name="activePath">The active path currently navigated.</param> | |||
/// <param name="pathSpecification">The path specification.</param> | |||
public override void CollectSearchIndexEntries(List<SearchIndexEntry> collectedEntries, NavigatedPath activePath, PathSpecification pathSpecification) | |||
/// <param name="navigationContext">The navigation context.</param> | |||
public override void CollectSearchIndexEntries(List<SearchIndexEntry> collectedEntries, NavigatedPath activePath, NavigationContext navigationContext) | |||
{ | |||
activePath.Push(this); | |||
// simply convert ourselves into an entry if we're not an index | |||
if(!this.IsIndexElement) | |||
{ | |||
var toAdd = new SearchIndexEntry(); | |||
toAdd.Fill(this.MarkdownFromFile, this.GetTargetURL(pathSpecification), this.Name, activePath); | |||
toAdd.Fill(this.MarkdownFromFile, this.GetTargetURL(navigationContext.PathSpecification), this.Name, activePath); | |||
collectedEntries.Add(toAdd); | |||
} | |||
activePath.Pop(); | |||
@@ -152,9 +154,9 @@ namespace Docnet | |||
/// </summary> | |||
/// <param name="navigatedPath">The navigated path to the current element, which doesn't necessarily have to be this element.</param> | |||
/// <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 override string GenerateToCFragment(NavigatedPath navigatedPath, string relativePathToRoot, PathSpecification pathSpecification) | |||
public override string GenerateToCFragment(NavigatedPath navigatedPath, string relativePathToRoot, NavigationContext navigationContext) | |||
{ | |||
// index elements are rendered in the parent container. | |||
if(this.IsIndexElement) | |||
@@ -162,7 +164,7 @@ namespace Docnet | |||
return string.Empty; | |||
} | |||
return PerformGenerateToCFragment(navigatedPath, relativePathToRoot, pathSpecification); | |||
return PerformGenerateToCFragment(navigatedPath, relativePathToRoot, navigationContext); | |||
} | |||
@@ -172,9 +174,9 @@ namespace Docnet | |||
/// </summary> | |||
/// <param name="navigatedPath">The navigated path.</param> | |||
/// <param name="relativePathToRoot">The relative path to root.</param> | |||
/// <param name="pathSpecification">The path specification.</param> | |||
/// <param name="navigationContext">The navigation context.</param> | |||
/// <returns></returns> | |||
public string PerformGenerateToCFragment(NavigatedPath navigatedPath, string relativePathToRoot, PathSpecification pathSpecification) | |||
public string PerformGenerateToCFragment(NavigatedPath navigatedPath, string relativePathToRoot, NavigationContext navigationContext) | |||
{ | |||
// we can't navigate deeper from here. If we are the element being navigated to, we are the current and will have to emit any additional relative URLs too. | |||
bool isCurrent = navigatedPath.Contains(this); | |||
@@ -190,15 +192,15 @@ 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(pathSpecification), | |||
this.GetFinalTargetUrl(navigationContext.PathSpecification), | |||
this.Name)); | |||
if(isCurrent && _relativeH2LinksOnPage.Any()) | |||
if(isCurrent && _relativeLinksOnPage.Any()) | |||
{ | |||
// generate relative links | |||
fragments.Add(string.Format("<ul class=\"{0}\">", this.ParentContainer.IsRoot ? "currentrelativeroot" : "currentrelative")); | |||
foreach(var p in _relativeH2LinksOnPage) | |||
foreach(var p in _relativeLinksOnPage) | |||
{ | |||
fragments.Add(string.Format("<li class=\"tocentry\"><a href=\"#{0}\">{1}</a></li>", p.Item1, p.Item2)); | |||
fragments.Add(string.Format("<li class=\"tocentry\"><a href=\"#{0}\">{1}</a></li>", p.Id, p.Name)); | |||
} | |||
fragments.Add("</ul>"); | |||
} | |||