1 module tocbuilder;
2 
3 import std.algorithm;
4 import std.stdio;
5 
6 private struct TocItem
7 {
8 	string name;
9 	string url;
10 	TocItem[] items;
11 	void write(File output, size_t indent = 0)
12 	{
13 		immutable hasChildren = items.length != 0;
14 		foreach (i; 0 .. indent)
15 			output.write("    ");
16 		if (url !is null)
17 			output.writeln(`<li><a target="docframe" href="`, url, `">`, name, `</a></li>`);
18 		else
19 			output.writeln(`<li><span onclick="toggleChildren(this);">`, name, `</span>`);
20 		if (hasChildren)
21 		{
22 			foreach (i; 0 .. indent)
23 				output.write("    ");
24 			output.writeln(`<ul>`);
25 		}
26 		foreach (item; items)
27 			item.write(output, indent + 1);
28 		if (hasChildren)
29 		{
30 			foreach (i; 0 .. indent)
31 				output.write("    ");
32 			output.writeln(`</ul></li>`);
33 		}
34 	}
35 }
36 
37 TocItem[] buildTree(string[] strings, string[string] links, size_t offset = 0)
38 {
39 	TocItem[] items;
40 	size_t i = 0;
41 	while (i < strings.length)
42 	{
43 		size_t j = i + 1;
44 		auto s = strings[i][offset .. $].findSplit(".");
45 		immutable string prefix = s[0];
46 		immutable string suffix = s[2];
47 		TocItem item;
48 		item.name = strings[i][offset .. offset + prefix.length];
49 		if (prefix.length != 0 && suffix.length != 0)
50 		{
51 			while (j < strings.length && strings[j][offset .. $].startsWith(prefix ~ s[1]))
52 				j++;
53 			if (i < j)
54 			{
55 				size_t o = offset + prefix.length + 1;
56 				item.items = buildTree(strings[i .. j], links, o);
57 			}
58 		}
59 		else
60 			item.url = links[strings[i]];
61 		items ~= item;
62 		i = j;
63 	}
64 	sort!((a, b) => a.name < b.name)(items);
65 	return items;
66 }