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 }