Merge branch 'master' of https://github.com/j3parker/dweb
Conflicts: pub/style/style.css
This commit is contained in:
commit
355a123c93
|
@ -1,3 +1,2 @@
|
||||||
pub/*
|
|
||||||
srv/*
|
srv/*
|
||||||
bin/web
|
bin/web
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
RewriteEngine on
|
RewriteEngine on
|
||||||
RewriteBase /~j3parker/
|
RewriteBase /~jy2wong/rofl/dweb/
|
||||||
RewriteRule ^pub/(.*) - [L]
|
RewriteRule ^pub/(.*) - [L]
|
||||||
RewriteRule ^(.*) /users/j3parker/www/bin/web [L]
|
RewriteRule ^(.*) /users/jy2wong/www/rofl/dweb/bin/web [L]
|
||||||
|
|
|
@ -116,6 +116,9 @@ padding: 0;}
|
||||||
|
|
||||||
/* # Horiz-side # */
|
/* # Horiz-side # */
|
||||||
#horiz-side-bar {
|
#horiz-side-bar {
|
||||||
|
width:100%;
|
||||||
|
clear: both;
|
||||||
|
border: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
15
src/config.d
15
src/config.d
|
@ -1,10 +1,15 @@
|
||||||
const string url_root = "/~j3parker/";
|
const string url_root = "/~j3parker/";
|
||||||
const string dweb_root = "/users/j3parker/www/";
|
|
||||||
const string site_root = dweb_root ~ "srv/";
|
|
||||||
|
|
||||||
const string site_title = "This is a Title";
|
const string site_title = "This is a Title";
|
||||||
const string site_subtitle = "but this is a subtitle";
|
const string site_subtitle = "but this is a subtitle";
|
||||||
|
|
||||||
const bool nav_tree_vert = true;
|
const bool nav_tree_vert = false;
|
||||||
const bool nav_tree_chev = true;
|
const bool nav_tree_chev = false;
|
||||||
const bool page_container = false;
|
const bool page_container = true;
|
||||||
|
|
||||||
|
string[string] handlers;
|
||||||
|
|
||||||
|
void init_handlers() {
|
||||||
|
handlers["*.md"] = "contrib/Markdown.pl";
|
||||||
|
handlers["changelog"] = "changelog.sh";
|
||||||
|
}
|
||||||
|
|
169
src/web.d
169
src/web.d
|
@ -1,105 +1,62 @@
|
||||||
//#!/usr/bin/rdmd
|
//#!/usr/bin/rdmd
|
||||||
import std.stdio;
|
import std.stdio, std.path, std.process, std.file, std.array, std.string, std.algorithm, std.datetime, std.ascii;
|
||||||
import std.process;
|
|
||||||
import std.file;
|
|
||||||
import std.array;
|
|
||||||
import std.string;
|
|
||||||
import std.algorithm;
|
|
||||||
import config;
|
import config;
|
||||||
|
|
||||||
|
string dweb_root;
|
||||||
|
|
||||||
string indent = "";
|
string indent = "";
|
||||||
void html(string s) { writeln(indent ~ s); }
|
void html(string s) { writeln(indent ~ s); }
|
||||||
void html_pop(string s) { indent = indent[0..max(0, $-4)]; html(s); }
|
void html_pop(string s) { indent = indent[0..max(0, $-4)]; html(s); }
|
||||||
void html_push(string s) { html(s); indent ~= " "; }
|
void html_push(string s) { html(s); indent ~= " "; }
|
||||||
|
|
||||||
void write_link(string root, string file, bool expand) {
|
void write_link(string to, bool expand) {
|
||||||
bool isdir = dirExists(file);
|
bool isdir = dirExists(dweb_root ~ "/srv/" ~ to[url_root.length..$]);
|
||||||
string flair = nav_tree_chev? (expand? "» " : "› ") : "";
|
string flair = nav_tree_chev? (expand? "» " : "› ") : "";
|
||||||
html_push("<li" ~ (expand? " class=\"thisPage\" " : "") ~ ">");
|
html_push("<li" ~ (expand? " class=\"thisPage\" " : "") ~ ">");
|
||||||
html("<a href=\"" ~ construct_rel_link(root, file) ~ "\">"
|
html("<a href=\"" ~ to ~ (isdir ? "/" : "") ~ "\">"
|
||||||
~ flair ~last_in_path(file) ~ (isdir ? "/" : "")
|
~ flair ~ baseName(to) ~ (isdir ? "/" : "") ~ "</a>");
|
||||||
~ "</a>");
|
|
||||||
html_pop("</li>");
|
html_pop("</li>");
|
||||||
}
|
}
|
||||||
|
|
||||||
void nav_tree_r(string root, string cur_loc, string[] subdirs) {
|
void nav_tree_r(string url, string cur_loc, string[] subdirs) {
|
||||||
string[] dirs = dir(cur_loc);
|
string[] dirs = array(map!"a.name"(dirEntries(dweb_root ~ "/srv/" ~ cur_loc, SpanMode.shallow)));
|
||||||
|
sort(dirs);
|
||||||
if (dirs.length == 0) return;
|
if (dirs.length == 0) return;
|
||||||
html_push("<ul>");
|
bool inserted_ul = false;
|
||||||
bool next = false;
|
bool next = false;
|
||||||
string next_loc;
|
string next_loc;
|
||||||
foreach(string s; dirs) {
|
foreach(string s; dirs) {
|
||||||
bool hidden = last_in_path(s).length > 0 && last_in_path(s)[0] == '.';
|
s= s[(dweb_root ~ "/srv/").length..$];
|
||||||
bool expand = s[cur_loc.length..$] == (subdirs.length == 0 ? "" : subdirs[0]);
|
string name = stripExtension(baseName(s));
|
||||||
if (hidden && !expand) continue;
|
if (name.length == 0) continue; // e.g. ".md", should we do something else with these files?
|
||||||
write_link(root, s, expand);
|
if (name == "index") continue; // "index" will never appear in the nav_tree.
|
||||||
if (expand && isDir(cur_loc ~ subdirs[0])) {
|
if (name[0] == '@') continue; // hidden file
|
||||||
|
if (!inserted_ul) { html_push("<ul>"); inserted_ul = true; }
|
||||||
|
bool expand = subdirs.length > 0 && name == subdirs[0];
|
||||||
|
write_link(url_root ~ stripExtension(s), expand);
|
||||||
|
|
||||||
|
if (expand && isDir(dweb_root ~ "/srv/" ~ s)) {
|
||||||
if (nav_tree_vert) {
|
if (nav_tree_vert) {
|
||||||
html_push("<li>");
|
html_push("<li>");
|
||||||
nav_tree_r(root, cur_loc ~ subdirs[0] ~ "/", subdirs[1..$]);
|
nav_tree_r(url, (cur_loc == "" ? "" : cur_loc ~ "/") ~ subdirs[0], subdirs[1..$]);
|
||||||
html_pop("</li>");
|
html_pop("</li>");
|
||||||
} else {
|
} else {
|
||||||
next = true;
|
next = true;
|
||||||
next_loc = cur_loc ~ subdirs[0] ~ "/";
|
next_loc = (cur_loc == "" ? "" : cur_loc ~ "/") ~ subdirs[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
html_pop("</ul>");
|
|
||||||
if (next) nav_tree_r(root, next_loc, subdirs[1..$]);
|
if (inserted_ul) html_pop("</ul>");
|
||||||
|
if (next) nav_tree_r(url, next_loc, subdirs[1..$]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// this could be better
|
void do_nav_tree(string url) {
|
||||||
string[] dir(string path) {
|
|
||||||
string[] files;
|
|
||||||
foreach(string s; dirEntries(path, SpanMode.shallow)) {
|
|
||||||
if (s[max(0,$-8)..$] != "index.md") files ~= s;
|
|
||||||
}
|
|
||||||
sort(files);
|
|
||||||
return files;
|
|
||||||
}
|
|
||||||
|
|
||||||
void do_nav_tree(string path) {
|
|
||||||
try { if (isDir(path) && path[path.length - 1] != '/') { path = site_root; } }
|
|
||||||
catch (Exception e) { path = site_root; }
|
|
||||||
|
|
||||||
html_push("<div id=\"" ~ (nav_tree_vert ? "" : "horiz-") ~ "side-bar\">");
|
html_push("<div id=\"" ~ (nav_tree_vert ? "" : "horiz-") ~ "side-bar\">");
|
||||||
|
nav_tree_r(url, "", cast(string[])array(pathSplitter(url)));
|
||||||
string root = get_root_dir(path);
|
|
||||||
string[] subdirs = explode_slashes(path[site_root.length..$]);
|
|
||||||
nav_tree_r(root, site_root, subdirs);
|
|
||||||
|
|
||||||
html_pop("</div>\n");
|
html_pop("</div>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
string last_in_path(string path) {
|
|
||||||
auto i = max(path.length,1) - 1;
|
|
||||||
while (i-- > 0) if (path[i] == '/') return path[min(i+1,$)..$];
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
string chomp_slashes(string path) { return chompPrefix(chomp(path, "/"), "/"); }
|
|
||||||
string[] explode_slashes(string path) { return split(chomp_slashes(path), "/"); }
|
|
||||||
|
|
||||||
string get_root_dir(string path) {
|
|
||||||
if (path == "") return "";
|
|
||||||
if (isDir(path)) return path[path.length - 1] == '/' ? path : path ~ "/";
|
|
||||||
auto i = path.length - 1;
|
|
||||||
while (--i > 0) if (path[i] == '/') return path[0..i];
|
|
||||||
return "/";
|
|
||||||
}
|
|
||||||
|
|
||||||
string construct_rel_link(string src, string dst) {
|
|
||||||
string rel = "";
|
|
||||||
string[] srcs = explode_slashes(src);
|
|
||||||
string[] dsts = explode_slashes(dst);
|
|
||||||
ulong i = 0;
|
|
||||||
while(i < srcs.length && i < dsts.length && srcs[i] == dsts[i]) i++;
|
|
||||||
if (i == srcs.length && i == dsts.length) return ".";
|
|
||||||
foreach (ulong j; 0..(srcs.length - i)) rel ~= "../";
|
|
||||||
foreach (string s; dsts[i..$]) rel ~= s ~ "/";
|
|
||||||
return isDir(dst) ? rel : rel[0..$-1];
|
|
||||||
}
|
|
||||||
|
|
||||||
void not_found(string path) {
|
void not_found(string path) {
|
||||||
html("The page <code>" ~ path ~ "</code> does not exist. (404)");
|
html("The page <code>" ~ path ~ "</code> does not exist. (404)");
|
||||||
}
|
}
|
||||||
|
@ -108,6 +65,10 @@ void do_header() {
|
||||||
html_push("<div id=\"header\">");
|
html_push("<div id=\"header\">");
|
||||||
|
|
||||||
html_push("<div class=\"superHeader\">");
|
html_push("<div class=\"superHeader\">");
|
||||||
|
|
||||||
|
html_push("<div class=\"left\">");
|
||||||
|
html_pop("</div>");
|
||||||
|
|
||||||
html_push("<div class=\"right\">");
|
html_push("<div class=\"right\">");
|
||||||
html("<a href=\"" ~ url_root ~ "changelog\">changelog</a>");
|
html("<a href=\"" ~ url_root ~ "changelog\">changelog</a>");
|
||||||
html_pop("</div>");
|
html_pop("</div>");
|
||||||
|
@ -127,37 +88,42 @@ void do_header() {
|
||||||
html_pop("</div>\n");
|
html_pop("</div>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_markdown(string file) {
|
|
||||||
// sanity check file first?!?!?
|
|
||||||
html(shell("cat " ~ file ~ "|" ~ dweb_root ~ "bin/contrib/Markdown.pl"));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool fileExists(string path) { try { if (isFile(path)) return true; else return false; } catch (Exception e) { return false; } }
|
|
||||||
bool dirExists(string path) { try { if (isDir(path)) return true; else return false; } catch (Exception e) { return false; } }
|
bool dirExists(string path) { try { if (isDir(path)) return true; else return false; } catch (Exception e) { return false; } }
|
||||||
|
|
||||||
void do_content(string path) {
|
void do_content(string url) {
|
||||||
html_push("<div id=\"main-copy\"" ~ (nav_tree_vert? " class=\"main-copy-side-bar\"" : "") ~ ">");
|
html_push("<div id=\"main-copy\"" ~ (nav_tree_vert? " class=\"main-copy-side-bar\"" : "") ~ ">");
|
||||||
string url = path[site_root.length..$];
|
// first, see if we have something that wants to handle url outright
|
||||||
switch (url) {
|
foreach (string glob, string h; handlers) {
|
||||||
case "changelog":
|
if (globMatch(url, glob)) {
|
||||||
html(shell(dweb_root ~ "bin/changelog"));
|
html(shell(dweb_root ~ "/bin/" ~ h ~ " " ~ url));
|
||||||
break;
|
html_pop("</div>");
|
||||||
default:
|
return;
|
||||||
try {
|
}
|
||||||
if (isDir(path) && fileExists(path ~ "index.md")) path ~= "index.md";
|
|
||||||
if (fileExists(path)) do_markdown(path);
|
|
||||||
} catch (Exception e) {
|
|
||||||
not_found(path);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
html_pop("</div>\n");
|
// if that failed, see if we can handle the file
|
||||||
|
if (url == "" ? false : url[$-1] == '/') url ~= "index";
|
||||||
|
foreach (f; array(map!"a.name"(dirEntries(dirName(dweb_root ~ "/srv/" ~ url), SpanMode.shallow)))) {
|
||||||
|
if (isDir(f)) continue;
|
||||||
|
string name = baseName(f); name = name[0] == '@' ? name[1..$] : name;
|
||||||
|
if (stripExtension(name) == baseName(url)) {
|
||||||
|
foreach (string glob, string h; handlers) {
|
||||||
|
if (globMatch(name, glob)) {
|
||||||
|
html(shell(dweb_root ~ "/bin/" ~ h ~ " " ~ f));
|
||||||
|
html_pop("</div>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (baseName(url) != "index") not_found(url);
|
||||||
|
html_pop("</div>");
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_footer() {
|
void do_footer() {
|
||||||
html_push("<div id=\"footer\">");
|
html_push("<div id=\"footer\">");
|
||||||
|
|
||||||
html_push("<div class=\"left\">");
|
html_push("<div class=\"left\">");
|
||||||
html("<a href=\"" ~ url_root ~ ".dweb\">Powered by dweb</a>");
|
html("<a href=\"" ~ url_root ~ "dweb\">Powered by dweb</a>");
|
||||||
html_pop("</div>");
|
html_pop("</div>");
|
||||||
|
|
||||||
html_push("<div class=\"right\">");
|
html_push("<div class=\"right\">");
|
||||||
|
@ -167,22 +133,29 @@ void do_footer() {
|
||||||
html_pop("</div>\n");
|
html_pop("</div>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool evil(string s) {
|
||||||
|
foreach(char c; s) if (!isAlphaNum(c) && c != '/' && c != '-' && c != '_') return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void main(string[] args) {
|
void main(string[] args) {
|
||||||
|
init_handlers();
|
||||||
|
dweb_root = getcwd()[0..$-4]; // take out bin/
|
||||||
|
|
||||||
html("Content-type: text/html\n");
|
html("Content-type: text/html\n");
|
||||||
html("<!DOCTYPE html>");
|
html("<!DOCTYPE html>");
|
||||||
html_push("<html>\n");
|
html_push("<html>\n");
|
||||||
|
|
||||||
string url = getenv("SCRIPT_URL")[url_root.length..$];
|
string url = getenv("SCRIPT_URL")[url_root.length..$];
|
||||||
string path = site_root ~ url;
|
if (evil(url)) { html ("bad url."); return; }
|
||||||
|
|
||||||
string pagename = last_in_path(url);
|
string pagename = baseName(url);
|
||||||
if (pagename.length != 0) pagename = " - " ~ pagename;
|
if (pagename.length != 0) pagename = " - " ~ pagename;
|
||||||
pagename = site_title ~ pagename;
|
pagename = site_title ~ pagename;
|
||||||
|
|
||||||
html_push("<head>");
|
html_push("<head>");
|
||||||
html("<title>" ~ pagename ~ "</title>");
|
html("<title>" ~ pagename ~ "</title>");
|
||||||
html("<link rel=\"stylesheet\" href=\"" ~ url_root ~ "pub/style/style.css\" type=\"text/css\" media=\"screen, handheld\" title=\"default\">");
|
html("<link rel=\"stylesheet\" href=\"" ~ url_root ~ "pub/style/style.css\" type=\"text/css\" media=\"screen, handheld\" title=\"default\">");
|
||||||
html("<link rel=\"shortcut\" href=\"" ~ url_root ~ "pub/favicon.ico\" type=\"image/vnd.microsoft.icon\">");
|
|
||||||
html("<meta charset=\"UTF-8\">");
|
html("<meta charset=\"UTF-8\">");
|
||||||
html("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">");
|
html("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">");
|
||||||
html_pop("</head>\n");
|
html_pop("</head>\n");
|
||||||
|
@ -190,10 +163,10 @@ void main(string[] args) {
|
||||||
html_push("<body" ~ (page_container? " style=\"text-align: center\"" : "")~ ">");
|
html_push("<body" ~ (page_container? " style=\"text-align: center\"" : "")~ ">");
|
||||||
if (page_container) html_push("<div id=\"container\">");
|
if (page_container) html_push("<div id=\"container\">");
|
||||||
do_header();
|
do_header();
|
||||||
do_nav_tree(path);
|
do_nav_tree(url);
|
||||||
do_content(path);
|
do_content(url);
|
||||||
do_footer();
|
do_footer();
|
||||||
if (page_container) html_push("</div>");
|
if (page_container) html_pop("</div>");
|
||||||
html_pop("</body>\n");
|
html_pop("</body>\n");
|
||||||
|
|
||||||
html_pop("</html>");
|
html_pop("</html>");
|
||||||
|
|
Loading…
Reference in New Issue