1 module docs4d; 2 3 import std.stdio; 4 import std.file; 5 import mustache; 6 import std.algorithm; 7 import std.array; 8 import std.string; 9 import std.regex; 10 import std.range; 11 import std.conv; 12 import dmarkdown; 13 14 struct Card 15 { 16 string name; 17 string description; 18 string category; 19 Param[] params; 20 Example[] examples; 21 Link[] links; 22 string fileLocation; 23 } 24 25 struct Param 26 { 27 string type; 28 string id; 29 string description; 30 ParamType paramType; 31 } 32 33 struct Example 34 { 35 string code; 36 } 37 38 enum ParamType 39 { 40 INPUT,OUTPUT 41 } 42 43 struct Link 44 { 45 string text; 46 string url; 47 string active = ""; 48 } 49 50 struct Page 51 { 52 string filename; 53 string name; 54 Link[] links; 55 string markdownFile; 56 57 string html(){ 58 auto markdown = readText(markdownFile); 59 return filterMarkdown(markdown); 60 } 61 62 } 63 64 class DocGen 65 { 66 67 string name; 68 string ver; 69 Page[] pages; 70 Card[] cards; 71 Link[] links; 72 alias MustacheEngine!(string) Mustache; 73 Mustache mustache; 74 Mustache.Context context; 75 string githubUrl; 76 77 this(string name, string ver, string githubUrl = ""){ 78 this.name = name; 79 this.ver = ver; 80 this.githubUrl = githubUrl; 81 this.context = new Mustache.Context; 82 mustache.path = "templates"; 83 mustache.level = Mustache.CacheLevel.no; 84 } 85 86 public DocGen withCards(Card[] cards) 87 { 88 this.cards = cards; 89 return this; 90 } 91 92 public DocGen withLinks(Link[] links) 93 { 94 this.links = links; 95 return this; 96 } 97 98 public DocGen withPages(Page[] pages) 99 { 100 this.pages = pages; 101 return this; 102 } 103 104 public void generate(){ 105 this.context["name"] = this.name; 106 this.context["ver"] = this.ver; 107 108 this.links.each!((link){ 109 auto subLinks = context.addSubContext("links"); 110 subLinks["text"] = link.text; 111 subLinks["url"] = link.url; 112 subLinks["active"] = link.active; 113 }); 114 115 foreach (ref card; this.cards.sort!((a,b)=> a.name.toLower() < b.name.toLower())) { 116 auto sub = context.addSubContext("cards"); 117 sub["name"] = card.name; 118 sub["category"] = card.category; 119 sub["description"] = card.description; 120 121 if(card.params.length > 0){ 122 sub["signature"] = card.params.map!(p => p.type).join(" → "); 123 sub.useSection("has_params"); 124 125 foreach(ref param ; card.params){ 126 if(param.paramType == ParamType.INPUT){ 127 auto sub2 = sub.addSubContext("input_params"); 128 sub2["type"] = param.type; 129 sub2["id"] = param.id; 130 sub2["desc"] = param.description; 131 } else { 132 auto sub3 = sub.addSubContext("return_value"); 133 sub.useSection("has_return"); 134 sub3["type"] = param.type; 135 sub3["desc"] = param.description; 136 } 137 } 138 139 } 140 141 if(card.examples.length > 0){ 142 sub.useSection("has_examples"); 143 foreach(ref example ; card.examples){ 144 auto sub4 = sub.addSubContext("examples"); 145 sub4["code"] = example.code; 146 } 147 } 148 149 if(card.links.length > 0){ 150 sub.useSection("has_see_also"); 151 foreach(ref link ; card.links){ 152 auto sub4 = sub.addSubContext("see_also"); 153 sub4["text"] = link.text; 154 sub4["url"] = link.url; 155 } 156 } 157 158 if(!card.fileLocation.empty){ 159 sub.useSection("has_gh"); 160 sub["gh"] = this.githubUrl ~ "/" ~ card.fileLocation; 161 } 162 163 } 164 165 // make target dir 166 if(exists("Docs")){ 167 rmdirRecurse("docs"); 168 } 169 mkdir("docs"); 170 copy("resources/main.js","docs/main.js"); 171 copy("resources/style.css","docs/style.css"); 172 mkdir("docs/fonts"); 173 copy("resources/fonts/glyphicons-halflings-regular.woff2","docs/fonts/glyphicons-halflings-regular.woff2"); 174 175 std.file.write("docs/documentation.html",mustache.render("documentation", context)); 176 177 foreach(ref page ; pages){ 178 page.links.each!((link){ 179 auto subLinks = context.addSubContext("page_links"); 180 subLinks["text"] = link.text; 181 subLinks["url"] = link.url; 182 subLinks["active"] = link.active; 183 }); 184 context["page_html"] = page.html(); 185 186 std.file.write("docs/" ~ page.filename,mustache.render("page", context)); 187 188 } 189 190 } 191 192 } 193 194