7e175538ef8c96912e10eeafc4cda4a2b7c6093f
[public/www-new.git] / src / web.d
1 //#!/usr/bin/rdmd
2 import std.stdio;
3 import std.process;
4 import std.file;
5 import std.array;
6 import std.string;
7 import std.algorithm;
8 import config;
9
10 string indent = "";
11 void html(string s) { writeln(indent ~ s); }
12 void html_pop(string s) { indent = indent[0..max(0, $-4)]; html(s); }
13 void html_push(string s) { html(s); indent ~= "    "; }
14
15 void write_link(string root, string file, bool expand) {
16   bool isdir = dirExists(file);
17   string flair = nav_tree_chev? (expand? "» " : "› ") : "";
18   html_push("<li" ~ (expand? " class=\"thisPage\" " : "") ~ ">");
19   html("<a href=\"" ~ construct_rel_link(root, file) ~ "\">"
20         ~ flair ~last_in_path(file) ~ (isdir ? "/" : "")
21         ~ "</a>");
22   html_pop("</li>");
23 }
24
25 void nav_tree_r(string root, string cur_loc, string[] subdirs) {
26   string[] dirs = dir(cur_loc);
27   if (dirs.length == 0) return;
28   html_push("<ul>");
29   bool next = false;
30   string next_loc;
31   foreach(string s; dirs) {
32     bool hidden = last_in_path(s).length > 0 && last_in_path(s)[0] == '.';
33     bool expand = s[cur_loc.length..$] == (subdirs.length == 0 ? "" : subdirs[0]);
34     if (hidden && !expand) continue;
35     write_link(root, s, expand);
36     if (expand && isDir(cur_loc ~ subdirs[0])) {
37       if (nav_tree_vert) {
38         html_push("<li>");
39         nav_tree_r(root, cur_loc ~ subdirs[0] ~ "/", subdirs[1..$]);
40         html_pop("</li>");
41       } else {
42         next = true;
43         next_loc = cur_loc ~ subdirs[0] ~ "/";
44       }
45     }
46   }
47   html_pop("</ul>");
48   if (next) nav_tree_r(root, next_loc, subdirs[1..$]);
49 }
50
51 // this could be better
52 string[] dir(string path) {
53   string[] files;
54   foreach(string s; dirEntries(path, SpanMode.shallow)) {
55     if (s[max(0,$-8)..$] != "index.md") files ~= s;
56   }
57   sort(files);
58   return files;
59 }
60
61 void do_nav_tree(string path) {
62   try { if (isDir(path) && path[path.length - 1] != '/') { path = site_root; } }
63   catch (Exception e) { path = site_root; }
64
65   html_push("<div id=\"" ~ (nav_tree_vert ? "" : "horiz-") ~ "side-bar\">");
66
67   string root = get_root_dir(path);
68   string[] subdirs = explode_slashes(path[site_root.length..$]);
69   nav_tree_r(root, site_root, subdirs);
70
71   html_pop("</div>\n");
72 }
73
74 string last_in_path(string path) {
75   auto i = max(path.length,1) - 1;
76   while (i-- > 0) if (path[i] == '/') return path[min(i+1,$)..$];
77   return path;
78 }
79
80 string chomp_slashes(string path) { return chompPrefix(chomp(path, "/"), "/"); }
81 string[] explode_slashes(string path) { return split(chomp_slashes(path), "/"); }
82
83 string get_root_dir(string path) {
84   if (path == "") return "";
85   if (isDir(path)) return path[path.length - 1] == '/' ? path : path ~ "/";
86   auto i = path.length - 1;
87   while (--i > 0) if (path[i] == '/') return path[0..i];
88   return "/";
89 }
90
91 string construct_rel_link(string src, string dst) {
92   string rel = "";
93   string[] srcs = explode_slashes(src);
94   string[] dsts = explode_slashes(dst);
95   ulong i = 0;
96   while(i < srcs.length && i < dsts.length && srcs[i] == dsts[i]) i++;
97   if (i == srcs.length && i == dsts.length) return ".";
98   foreach (ulong j; 0..(srcs.length - i)) rel ~= "../";
99   foreach (string s; dsts[i..$]) rel ~= s ~ "/"; 
100   return isDir(dst) ? rel : rel[0..$-1];
101 }
102
103 void not_found(string path) {
104   html("The page <code>" ~ path ~ "</code> does not exist. (404)");
105 }
106
107 void do_header() {
108   html_push("<div id=\"header\">");
109   
110   html_push("<div class=\"superHeader\">");
111   html_push("<div class=\"right\">");
112   html("<a href=\"" ~ url_root ~ "changelog\">changelog</a>");
113   html_pop("</div>");
114   
115   html_pop("</div>");
116
117   html_push("<div class=\"midHeader\">");
118   html_push("<h1 class=\"headerTitle\">");
119   html("<a href=\"" ~ url_root ~ "\">" ~ site_title ~ " <span id=\"headerSubTitle\">" ~ site_subtitle ~ "</span></a>");
120   html_pop("</h1>");
121   html_pop("</div>");
122   
123   html_push("<div class=\"subHeader\">");
124   html("<br>");
125   html_pop("</div>");
126   
127   html_pop("</div>\n");
128 }
129
130 void do_markdown(string file) {
131   // sanity check file first?!?!?
132   html(shell("cat " ~ file ~ "|" ~ dweb_root ~ "bin/contrib/Markdown.pl"));
133 }
134
135 bool fileExists(string path) { try { if (isFile(path)) return true; else return false; } catch (Exception e) { return false; } }
136 bool dirExists(string path)  { try { if (isDir(path))  return true; else return false; } catch (Exception e) { return false; } }
137
138 void do_content(string path) {
139   html_push("<div id=\"main-copy\"" ~ (nav_tree_vert? " class=\"main-copy-side-bar\"" : "")  ~ ">");
140   string url = path[site_root.length..$];
141   switch (url) {
142     case "changelog":
143       html(shell(dweb_root ~ "bin/changelog"));
144       break;
145     default:
146       try {
147         if (isDir(path) && fileExists(path ~ "index.md")) path ~= "index.md";
148         if (fileExists(path)) do_markdown(path);
149       } catch (Exception e) {
150         not_found(path);
151       }
152   }
153   html_pop("</div>\n");
154 }
155
156 void do_footer() {
157   html_push("<div id=\"footer\">");
158
159   html_push("<div class=\"left\">");
160   html("<a href=\"" ~ url_root ~ ".dweb\">Powered by dweb</a>");
161   html_pop("</div>");
162
163   html_push("<div class=\"right\">");
164   html("&nbsp;");
165   html_pop("</div>");
166
167   html_pop("</div>\n");
168 }
169
170 void main(string[] args) {
171   html("Content-type: text/html\n");
172   html("<!DOCTYPE html>");
173   html_push("<html>\n");
174
175   string url = getenv("SCRIPT_URL")[url_root.length..$];
176   string path = site_root ~ url;
177   
178   string pagename = last_in_path(url);
179   if (pagename.length != 0) pagename = " - " ~ pagename;
180   pagename = site_title ~ pagename;
181   
182   html_push("<head>");
183   html("<title>" ~ pagename ~ "</title>");
184   html("<link rel=\"stylesheet\" href=\"" ~ url_root ~ "pub/style/style.css\" type=\"text/css\" media=\"screen, handheld\" title=\"default\">");
185   html("<link rel=\"shortcut\" href=\"" ~ url_root ~ "pub/favicon.ico\" type=\"image/vnd.microsoft.icon\">");
186   html("<meta charset=\"UTF-8\">");
187   html("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">");
188   html_pop("</head>\n");
189   
190   html_push("<body" ~ (page_container? " style=\"text-align: center\"" : "")~ ">");
191   if (page_container) html_push("<div id=\"container\">");
192   do_header();
193   do_nav_tree(path);
194   do_content(path);
195   do_footer();
196   if (page_container) html_push("</div>");
197   html_pop("</body>\n");
198
199   html_pop("</html>");
200 }