-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNavigationGraph.cs
More file actions
77 lines (67 loc) · 2.12 KB
/
Copy pathNavigationGraph.cs
File metadata and controls
77 lines (67 loc) · 2.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
namespace ShellDocs.Core;
public class NavigationGraph
{
public NavigationNode Root { get; }
private readonly Dictionary<string, NavigationNode> _byUrl;
private readonly List<NavigationNode> _flatPages;
public NavigationGraph(NavigationNode root)
{
Root = root;
_byUrl = new Dictionary<string, NavigationNode>(StringComparer.OrdinalIgnoreCase);
_flatPages = new List<NavigationNode>();
Index(root);
}
public NavigationNode? ResolveByUrl(string url)
{
var key = Normalize(url);
return _byUrl.TryGetValue(key, out var node) ? node : null;
}
public (NavigationNode? Prev, NavigationNode? Next) GetPrevNext(NavigationNode node)
{
var i = _flatPages.IndexOf(node);
if (i < 0) return (null, null);
var prev = i > 0 ? _flatPages[i - 1] : null;
var next = i < _flatPages.Count - 1 ? _flatPages[i + 1] : null;
return (prev, next);
}
public IReadOnlyList<NavigationNode> GetBreadcrumb(NavigationNode node)
{
var chain = new List<NavigationNode>();
var current = node;
while (current is not null && current != Root)
{
chain.Add(current);
current = current.Parent;
}
chain.Reverse();
return chain;
}
public IEnumerable<NavigationNode> Flatten()
{
return FlattenFrom(Root);
}
private static IEnumerable<NavigationNode> FlattenFrom(NavigationNode node)
{
yield return node;
foreach (var child in node.Children)
{
foreach (var n in FlattenFrom(child)) yield return n;
}
}
private void Index(NavigationNode node)
{
if (node.Kind == NodeKind.Page && !string.IsNullOrEmpty(node.Url))
{
_byUrl[Normalize(node.Url)] = node;
_flatPages.Add(node);
}
foreach (var child in node.Children) Index(child);
}
private static string Normalize(string url)
{
var s = url.Trim();
if (!s.StartsWith('/')) s = "/" + s;
if (s.Length > 1 && s.EndsWith('/')) s = s[..^1];
return s;
}
}