Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support automatic inclusion of files using ** (e.g. reference/**) #58

Merged
merged 2 commits into from
Jun 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/DocNet/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ public NavigationLevel Pages
if(_pages == null)
{
JObject rawPages = _configData.Pages;
_pages = new NavigationLevel() {Name = "Home", IsRoot = true};
_pages = new NavigationLevel(Source) {Name = "Home", IsRoot = true};
_pages.Load(rawPages);
}
return _pages;
Expand Down
160 changes: 137 additions & 23 deletions src/DocNet/NavigationLevel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,30 +33,65 @@ namespace Docnet
{
public class NavigationLevel : NavigationElement<List<INavigationElement>>
{
public NavigationLevel() : base()
#region Members
private readonly string _rootDirectory;
#endregion

public NavigationLevel(string rootDirectory)
: base()
{
this._rootDirectory = rootDirectory;
this.Value = new List<INavigationElement>();
}


public void Load(JObject dataFromFile)
{
foreach(KeyValuePair<string, JToken> child in dataFromFile)
foreach (KeyValuePair<string, JToken> child in dataFromFile)
{
INavigationElement toAdd;
if(child.Value.Type == JTokenType.String)
if (child.Value.Type == JTokenType.String)
{
var nameToUse = child.Key;

var isIndexElement = child.Key == "__index";
if(isIndexElement)
if (isIndexElement)
{
nameToUse = this.Name;
}
toAdd = new SimpleNavigationElement() { Name = nameToUse, Value = child.Value.ToObject<string>(), IsIndexElement = isIndexElement};

var childValue = child.Value.ToObject<string>();
if (childValue.EndsWith("**"))
{
var path = childValue.Replace("**", string.Empty)
.Replace('\\', Path.DirectorySeparatorChar)
.Replace('/', Path.DirectorySeparatorChar);

if (!Path.IsPathRooted(path))
{
path = Path.Combine(_rootDirectory, path);
}

toAdd = CreateGeneratedLevel(path);
toAdd.Name = nameToUse;
}
else
{
toAdd = new SimpleNavigationElement
{
Name = nameToUse,
Value = childValue,
IsIndexElement = isIndexElement
};
}
}
else
{
var subLevel = new NavigationLevel() { Name = child.Key, IsRoot = false};
var subLevel = new NavigationLevel(_rootDirectory)
{
Name = child.Key,
IsRoot = false
};
subLevel.Load((JObject)child.Value);
toAdd = subLevel;
}
Expand All @@ -74,7 +109,7 @@ public void Load(JObject dataFromFile)
public override void CollectSearchIndexEntries(List<SearchIndexEntry> collectedEntries, NavigatedPath activePath)
{
activePath.Push(this);
foreach(var element in this.Value)
foreach (var element in this.Value)
{
element.CollectSearchIndexEntries(collectedEntries, activePath);
}
Expand All @@ -91,7 +126,7 @@ public override void GenerateOutput(Config activeConfig, NavigatedPath activePat
{
activePath.Push(this);
int i = 0;
while(i<this.Value.Count)
while (i < this.Value.Count)
{
var element = this.Value[i];
element.GenerateOutput(activeConfig, activePath);
Expand All @@ -110,15 +145,15 @@ public override void GenerateOutput(Config activeConfig, NavigatedPath activePat
public override string GenerateToCFragment(NavigatedPath navigatedPath, string relativePathToRoot)
{
var fragments = new List<string>();
if(!this.IsRoot)
if (!this.IsRoot)
{
fragments.Add("<li class=\"tocentry\">");
}
if(navigatedPath.Contains(this))
if (navigatedPath.Contains(this))
{
// we're expanded. If we're not root and on the top of the navigated path stack, our index page is the page we're currently generating the ToC for, so
// we have to mark the entry as 'current'
if(navigatedPath.Peek() == this && !this.IsRoot)
if (navigatedPath.Peek() == this && !this.IsRoot)
{
fragments.Add("<ul class=\"current\">");
}
Expand All @@ -130,24 +165,24 @@ public override string GenerateToCFragment(NavigatedPath navigatedPath, string r
// 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.IndexElement;
if(indexElement == null)
if (indexElement == null)
{
fragments.Add(string.Format("{0}{1}</span></li>", elementStartTag, this.Name));
}
else
{
if(this.IsRoot)
if (this.IsRoot)
{
fragments.Add(indexElement.PerformGenerateToCFragment(navigatedPath, relativePathToRoot));
}
else
{
fragments.Add(string.Format("{0}<a href=\"{1}{2}\">{3}</a></span></li>", elementStartTag, relativePathToRoot, HttpUtility.UrlPathEncode(indexElement.TargetURL),
fragments.Add(string.Format("{0}<a href=\"{1}{2}\">{3}</a></span></li>", elementStartTag, relativePathToRoot, HttpUtility.UrlPathEncode(indexElement.TargetURL),
this.Name));
}
}
// then the elements in the container. Index elements are skipped here.
foreach(var element in this.Value)
foreach (var element in this.Value)
{
fragments.Add(element.GenerateToCFragment(navigatedPath, relativePathToRoot));
}
Expand All @@ -156,24 +191,102 @@ public override string GenerateToCFragment(NavigatedPath navigatedPath, string r
else
{
// just a link
fragments.Add(string.Format("<span class=\"navigationgroup\"><i class=\"fa fa-caret-right\"></i> <a href=\"{0}{1}\">{2}</a></span>",
fragments.Add(string.Format("<span class=\"navigationgroup\"><i class=\"fa fa-caret-right\"></i> <a href=\"{0}{1}\">{2}</a></span>",
relativePathToRoot, HttpUtility.UrlPathEncode(this.TargetURL), this.Name));
}
if(!this.IsRoot)
if (!this.IsRoot)
{
fragments.Add("</li>");
}
return string.Join(Environment.NewLine, fragments.ToArray());
}

private NavigationLevel CreateGeneratedLevel(string path)
{
var root = new NavigationLevel(_rootDirectory)
{
ParentContainer = this
};

foreach (var mdFile in Directory.GetFiles(path, "*.md", SearchOption.TopDirectoryOnly))
{
var name = FindTitleInMdFile(mdFile);
if (string.IsNullOrWhiteSpace(name))
{
continue;
}

var relativeFilePath = Utils.MakeRelativePath(mdFile, _rootDirectory);

var item = new SimpleNavigationElement
{
Name = name,
Value = relativeFilePath,
ParentContainer = root
};

root.Value.Add(item);
}

foreach (var directory in Directory.GetDirectories(path, "*", SearchOption.TopDirectoryOnly))
{
var directoryInfo = new DirectoryInfo(directory);

var subDirectoryNavigationElement = CreateGeneratedLevel(directory);

subDirectoryNavigationElement.Name = directoryInfo.Name;
subDirectoryNavigationElement.ParentContainer = root;

root.Value.Add(subDirectoryNavigationElement);
}

return root;
}

private string FindTitleInMdFile(string path)
{
var title = string.Empty;

using (var fileStream = File.OpenRead(path))
{
using (var streamReader = new StreamReader(fileStream))
{
var line = string.Empty;

while (string.IsNullOrWhiteSpace(line))
{
line = streamReader.ReadLine();

if (!string.IsNullOrWhiteSpace(line))
{
line = line.Trim();

while (line.StartsWith("#"))
{
line = line.Substring(1).Trim();
}

if (!string.IsNullOrWhiteSpace(line))
{
title = line;
break;
}
}
}
}
}

return title;
}


#region Properties
public override string TargetURL
{
get
{
var defaultElement = this.IndexElement;
if(defaultElement == null)
if (defaultElement == null)
{
return string.Empty;
}
Expand All @@ -187,20 +300,20 @@ public SimpleNavigationElement IndexElement
get
{
var toReturn = this.Value.FirstOrDefault(e => e.IsIndexElement) as SimpleNavigationElement;
if(toReturn == null)
if (toReturn == null)
{
// no index element, add an artificial one.
var path = string.Empty;
if(this.ParentContainer != null)
if (this.ParentContainer != null)
{
path = Path.GetDirectoryName(this.ParentContainer.TargetURL);
}
var nameToUse = this.Name.Replace(".", "").Replace('/', '_').Replace("\\", "_").Replace(":", "").Replace(" ", "");
if(string.IsNullOrWhiteSpace(nameToUse))
if (string.IsNullOrWhiteSpace(nameToUse))
{
return null;
}
toReturn = new SimpleNavigationElement() {ParentContainer = this, Value = string.Format("{0}{1}.md", path, nameToUse), Name = this.Name, IsIndexElement = true};
toReturn = new SimpleNavigationElement() { ParentContainer = this, Value = string.Format("{0}{1}.md", path, nameToUse), Name = this.Name, IsIndexElement = true };
this.Value.Add(toReturn);
}

Expand All @@ -216,7 +329,8 @@ public override bool IsIndexElement
{
// never an index
get { return false; }
set {
set
{
// nop;
}
}
Expand Down