dweb v0.1
This commit is contained in:
commit
c3c1116e5f
|
@ -0,0 +1,3 @@
|
|||
pub/*
|
||||
srv/*
|
||||
bin/web
|
|
@ -0,0 +1,4 @@
|
|||
RewriteEngine on
|
||||
RewriteBase /~j3parker/
|
||||
RewriteRule ^pub/(.*) - [L]
|
||||
RewriteRule ^(.*) /users/j3parker/www/bin/web [L]
|
|
@ -0,0 +1,2 @@
|
|||
Options +ExecCGI
|
||||
SetHandler cgi-script
|
|
@ -0,0 +1,3 @@
|
|||
echo "<ul>"
|
||||
git log --pretty=format:'<li>%s - %aN (%ae) <b>(%cr)</b></li>' --abbrev-commit --date=relative
|
||||
echo "</ul>"
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,335 @@
|
|||
/* Default werc style */
|
||||
|
||||
/* General style guidelines:
|
||||
- All font-size at least 14px (recommended 16px)
|
||||
- Line-height: 1.5 for paragraph body, 1.1 for header
|
||||
*/
|
||||
|
||||
body {
|
||||
color: black;
|
||||
background-color: white;
|
||||
font-family: Helvetica, Verdana, Arial, 'Liberation Sans', FreeSans, sans-serif;
|
||||
font-size: 84%; /* Enables font size scaling in MSIE */
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
/* # Header # */
|
||||
.superHeader {
|
||||
color: white;
|
||||
background-color: rgb(100,135,220);
|
||||
height: 1.6em;
|
||||
}
|
||||
|
||||
.superHeader img { vertical-align: bottom; }
|
||||
|
||||
.superHeader a {
|
||||
color: white;
|
||||
background-color: transparent;
|
||||
font-size: 91%;
|
||||
margin: 0;
|
||||
padding: 0 0.5ex 0 0.25ex;
|
||||
}
|
||||
|
||||
a { text-decoration: none; }
|
||||
a:hover { text-decoration: underline; }
|
||||
|
||||
.superHeader div {
|
||||
position: absolute;
|
||||
top: 0.40ex;
|
||||
}
|
||||
|
||||
.superHeader .left { left: 0.4em; }
|
||||
.superHeader .right { right: 0.4em; }
|
||||
|
||||
.midHeader {
|
||||
color: rgb(39,78,144);
|
||||
background-color: rgb(140,170,230);
|
||||
background-color: #ff6d06;
|
||||
border: solid 0 black;
|
||||
border-width: 2px 0;
|
||||
}
|
||||
|
||||
.headerTitle {
|
||||
color: black;
|
||||
font-size: 233%;
|
||||
font-weight: normal;
|
||||
margin: 0 0 0 4mm;
|
||||
padding: 0.25ex 0;
|
||||
}
|
||||
#headerSubTitle {
|
||||
font-size: 50%;
|
||||
font-style: italic;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
.headerTitle a { color: black; }
|
||||
.headerTitle a:hover { text-decoration: none; }
|
||||
|
||||
.subHeader {
|
||||
display: none;
|
||||
color: white;
|
||||
background-color: rgb(0,51,153);
|
||||
margin: 0;
|
||||
padding: 1ex 1ex 1ex 1.5mm;
|
||||
}
|
||||
|
||||
.subHeader a {
|
||||
color: white;
|
||||
background-color: transparent;
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
padding: 0 0.75ex 0 0.5ex;
|
||||
}
|
||||
|
||||
.superHeader .highlight, .subHeader .highlight {
|
||||
color: rgb(253,160,91);
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
|
||||
/* # Side # */
|
||||
#side-bar {
|
||||
width: 16em;
|
||||
float: left;
|
||||
clear: left;
|
||||
border-right: 1px solid #ddd;
|
||||
}
|
||||
|
||||
#side-bar div {
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.sideBarTitle {
|
||||
font-weight: bold;
|
||||
margin: 0 0 0.5em 2mm;
|
||||
padding: 1em 0 0 0;
|
||||
}
|
||||
|
||||
#side-bar ul {
|
||||
list-style-type: none;
|
||||
list-style-position: outside;
|
||||
margin: 0;
|
||||
padding: 0 0 0.3em 0;
|
||||
}
|
||||
|
||||
li ul {
|
||||
padding-left: 0.6em !important;
|
||||
}
|
||||
|
||||
#side-bar li {
|
||||
margin: 0;
|
||||
padding: 0.1ex 0; /* Circumvents a rendering bug (?) in MSIE 6.0 XXX should move to iehacks.css, this causes an ugly gap */
|
||||
}
|
||||
|
||||
#side-bar a {
|
||||
color: rgb(0,102,204);
|
||||
background-color: transparent;
|
||||
margin: 0;
|
||||
padding: 0.25em 1ex 0.25em 2mm;
|
||||
display: block;
|
||||
text-transform: capitalize;
|
||||
font-weight: bold!important;
|
||||
font-size: 102%;
|
||||
border-left: white solid 0.2em;
|
||||
}
|
||||
|
||||
.thisPage, .thisPage a {
|
||||
color: black!important;
|
||||
background-color: white;
|
||||
padding-left: 5mm;
|
||||
}
|
||||
|
||||
#side-bar a:hover {
|
||||
color: white;
|
||||
background-color: rgb(100,135,220);
|
||||
border-left: black solid 0.2em;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.sideBarText {
|
||||
line-height: 1.5em;
|
||||
margin: 0 0 1em 0;
|
||||
padding: 0 1.5ex 0 2.5mm;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#side-bar .sideBarText a {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
#side-bar .sideBarText a:hover {
|
||||
color: rgb(0,102,204);
|
||||
background-color: transparent;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
||||
/* # Main Copy # */
|
||||
#main-copy {
|
||||
max-width: 70em;
|
||||
color: black;
|
||||
background-color: transparent;
|
||||
text-align: justify;
|
||||
line-height: 1.5em;
|
||||
margin: 0em 0 0 16em;
|
||||
padding: 0.5mm 5mm 5mm 5mm;
|
||||
border-left: 1px solid #ddd;
|
||||
}
|
||||
|
||||
#bodyText {
|
||||
margin: 0 0 0 15.5em;
|
||||
padding: 2mm 5mm 2mm 5mm;
|
||||
}
|
||||
|
||||
#main-copy p {
|
||||
margin: 1em 1ex 1em 1ex !important; /* Need !important so troff-generated pages don't look totally squezed */
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#main-copy a {
|
||||
color: rgb(0,102,204);
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#main-copy a:hover {
|
||||
color: rgb(100,135,220);
|
||||
}
|
||||
|
||||
#main-copy h1, #main-copy h2 {
|
||||
color: rgb(0,102,204);
|
||||
background-color: transparent;
|
||||
font-size: 145.5%;
|
||||
font-weight: bold;
|
||||
margin: 2em 0 0 0;
|
||||
padding: 0.5ex 0 0.5ex 0.6ex;
|
||||
border-bottom: 2px solid rgb(0,102,204);
|
||||
}
|
||||
|
||||
#main-copy h2 {
|
||||
font-size: 115.5%;
|
||||
border-bottom: 1px solid rgb(0,102,204);
|
||||
}
|
||||
|
||||
#main-copy .topOfPage {
|
||||
color: rgb(0,102,204);
|
||||
background-color: transparent;
|
||||
font-size: 91%;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
margin: 3ex 1ex 0 0;
|
||||
padding: 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
dl {
|
||||
margin: 1em 1ex 2em 1ex;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: bold;
|
||||
margin: 0 0 0 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin: 0 0 2em 2em;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
/* # Footer # */
|
||||
#footer {
|
||||
color: white;
|
||||
background-color: rgb(100,135,220);
|
||||
padding: 1em;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
#footer .left {
|
||||
text-align: left;
|
||||
line-height: 1.55em;
|
||||
float: left;
|
||||
clear: left;
|
||||
}
|
||||
|
||||
#footer .right {
|
||||
text-align: right;
|
||||
line-height: 1.45em;
|
||||
}
|
||||
|
||||
#footer a {
|
||||
color: white;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
|
||||
/* GENERAL */
|
||||
|
||||
table {
|
||||
border: solid 1px black;
|
||||
}
|
||||
th {
|
||||
background-color: #abc;
|
||||
border: solid 1px black;
|
||||
text-align: center;
|
||||
}
|
||||
td {
|
||||
background-color: #def;
|
||||
border: solid 1px black;
|
||||
}
|
||||
|
||||
hr {
|
||||
border-width: 0px 0px 0.1em 0px;
|
||||
border-color: black;
|
||||
}
|
||||
|
||||
acronym, .titleTip {
|
||||
border-bottom: 1px solid #ddd;
|
||||
cursor: help;
|
||||
margin: 0;
|
||||
padding: 0 0 0.4px 0;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin-left: 2em;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border-left: 1px solid blue;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.smallCaps {
|
||||
font-size: 110%;
|
||||
font-variant: small-caps;
|
||||
}
|
||||
|
||||
.doNotDisplay { display: none; }
|
||||
|
||||
|
||||
.notify_errors,
|
||||
.notify_notes,
|
||||
.notify_success { padding: .8em; margin-bottom: 1em; border: 2px solid #ddd; }
|
||||
|
||||
.notify_errors { background: #FBE3E4; color: #8a1f11; border-color: #FBC2C4; }
|
||||
.notify_notes { background: #FFF6BF; color: #514721; border-color: #FFD324; }
|
||||
.notify_success { background: #E6EFC2; color: #264409; border-color: #C6D880; }
|
||||
.notify_errors a { color: #8a1f11; }
|
||||
.notify_notes a { color: #514721; }
|
||||
.notify_success a { color: #264409; }
|
||||
|
||||
|
||||
/* # Page/Handler specific # */
|
||||
h1.dir-list-head, ul.dir-list {
|
||||
text-transform: capitalize;
|
||||
font-weight: bold;
|
||||
}
|
||||
ul.sitemap-list a {
|
||||
text-transform: capitalize;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
dmd config.d web.d -ofweb && rm web.o && mv web ../bin/
|
|
@ -0,0 +1,6 @@
|
|||
const string url_root = "/~j3parker/";
|
||||
const string dweb_root = "/users/j3parker/www/";
|
||||
const string site_root = dweb_root ~ "srv/";
|
||||
|
||||
const string site_title = "Test Title";
|
||||
const string site_subtitle = "this is a subtitle";
|
|
@ -0,0 +1,186 @@
|
|||
//#!/usr/bin/rdmd
|
||||
import std.stdio;
|
||||
import std.process;
|
||||
import std.file;
|
||||
import std.array;
|
||||
import std.string;
|
||||
import std.algorithm;
|
||||
import config;
|
||||
|
||||
string indent = "";
|
||||
void html(string s) { writeln(indent ~ s); }
|
||||
void html_pop(string s) { indent = indent[0..max(0, $-4)]; html(s); }
|
||||
void html_push(string s) { html(s); indent ~= " "; }
|
||||
|
||||
void write_link(string root, string file, bool expand) {
|
||||
bool isdir = dirExists(file);
|
||||
html_push("<li>");
|
||||
html("<a href=\"" ~ construct_rel_link(root, file) ~ "\"" ~
|
||||
(expand? " class=\"thisPage\">» <i>" : ">› ")
|
||||
~ last_in_path(file) ~ (isdir ? "/" : "")
|
||||
~ (expand? "</i>" : "") ~ "</a>");
|
||||
html_pop("</li>");
|
||||
}
|
||||
|
||||
void nav_tree_r(string root, string cur_loc, string[] subdirs) {
|
||||
html_push("<ul>");
|
||||
foreach(string s; dir(cur_loc)) {
|
||||
if (s[max(0,$-8)..$]=="index.md") continue;
|
||||
bool hidden = last_in_path(s).length > 0 && last_in_path(s)[0] == '.';
|
||||
bool expand = s[cur_loc.length..$] == (subdirs.length == 0 ? "" : subdirs[0]);
|
||||
if (hidden && !expand) continue;
|
||||
write_link(root, s, expand);
|
||||
if (expand && isDir(cur_loc ~ subdirs[0])) {
|
||||
html_push("<li>");
|
||||
nav_tree_r(root, cur_loc ~ subdirs[0] ~ "/", subdirs[1..$]);
|
||||
html_pop("</li>");
|
||||
}
|
||||
}
|
||||
html_pop("</ul>");
|
||||
}
|
||||
|
||||
// this could be better
|
||||
string[] dir(string path) {
|
||||
string[] files;
|
||||
foreach(string s; dirEntries(path, SpanMode.shallow)) 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=\"side-bar\">");
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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) {
|
||||
html("The page <code>" ~ path ~ "</code> does not exist. (404)");
|
||||
}
|
||||
|
||||
void do_header() {
|
||||
html_push("<div id=\"header\">");
|
||||
|
||||
html_push("<div class=\"superHeader\">");
|
||||
html_push("<div class=\"right\">");
|
||||
html("<a href=\"" ~ url_root ~ "changelog\">changelog</a>");
|
||||
html_pop("</div>");
|
||||
|
||||
html_pop("</div>");
|
||||
|
||||
html_push("<div class=\"midHeader\">");
|
||||
html_push("<h1 class=\"headerTitle\">");
|
||||
html("<a href=\"" ~ url_root ~ "\">" ~ site_title ~ " <span id=\"headerSubTitle\">" ~ site_subtitle ~ "</span></a>");
|
||||
html_pop("</h1>");
|
||||
html_pop("</div>");
|
||||
|
||||
html_push("<div class=\"subHeader\">");
|
||||
html("<br>");
|
||||
html_pop("</div>");
|
||||
|
||||
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; } }
|
||||
|
||||
void do_content(string path) {
|
||||
html_push("<div id=\"main-copy\">");
|
||||
string url = path[site_root.length..$];
|
||||
switch (url) {
|
||||
case "changelog":
|
||||
html(shell(dweb_root ~ "bin/changelog"));
|
||||
break;
|
||||
default:
|
||||
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");
|
||||
}
|
||||
|
||||
void do_footer() {
|
||||
html_push("<div id=\"footer\">");
|
||||
|
||||
html_push("<div class=\"left\">");
|
||||
html("<a href=\"" ~ url_root ~ ".dweb\">Powered by dweb</a>");
|
||||
html_pop("</div>");
|
||||
|
||||
html_push("<div class=\"right\">");
|
||||
html(" ");
|
||||
html_pop("</div>");
|
||||
|
||||
html_pop("</div>\n");
|
||||
}
|
||||
|
||||
void main(string[] args) {
|
||||
html("Content-type: text/html\n");
|
||||
html("<!DOCTYPE html>");
|
||||
html_push("<html>\n");
|
||||
|
||||
string url = getenv("SCRIPT_URL")[url_root.length..$];
|
||||
string path = site_root ~ url;
|
||||
|
||||
string pagename = last_in_path(url);
|
||||
if (pagename.length != 0) pagename = " - " ~ pagename;
|
||||
pagename = site_title ~ pagename;
|
||||
|
||||
html_push("<head>");
|
||||
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=\"shortcut\" href=\"" ~ url_root ~ "pub/favicon.ico\" type=\"image/vnd.microsoft.icon\">");
|
||||
html("<meta charset=\"UTF-8\">");
|
||||
html("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">");
|
||||
html_pop("</head>\n");
|
||||
|
||||
html_push("<body>");
|
||||
do_header();
|
||||
do_nav_tree(path);
|
||||
do_content(path);
|
||||
do_footer();
|
||||
html_pop("</body>\n");
|
||||
|
||||
html_pop("</html>");
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
dweb - A simple website written in D
|
||||
=====
|
||||
dweb is a simple website framework based off the [werc][werc] software.
|
||||
|
||||
Its principles are:
|
||||
|
||||
- Database free, uses files and directories instead.
|
||||
- Written using the D programming language.
|
||||
- Minimize tedious work: eg., no need to ever write HTML, use markdown instead.
|
||||
- Very minimalist yet extensible codebase. Handlers for special things should be easy to add.
|
||||
|
||||
It was created because werc was annoying to deploy on UW Computer Science Club's Apache setup and because [Not Invented Here](http://en.wikipedia.org/wiki/Not_Invented_Here).
|
||||
|
||||
[werc]:http://werc.cat-v.org/
|
||||
[md]:http://daringfireball.net/projects/markdown
|
||||
|
||||
Install Guide
|
||||
------
|
||||
You will need:
|
||||
- An HTTP server with CGI support.
|
||||
- The D compiler.
|
||||
|
||||
Extract the contents into the location you want to serve webpages from. Edit the following files:
|
||||
|
||||
- <code>$DWEB_ROOT/.htaccess</code>: make the paths work for your setup.
|
||||
- <code>$DWEB_ROOT/src/config.d</code>: change these strings as necessary.
|
||||
- <code>$DWEB_ROOT/src/web.d</code>: this is the main web code.
|
||||
- <code>$DWEB_ROOT/pub/</code>: static content goes here.
|
||||
- <code>$DWEB_ROOT/srv/</code>: directories, markdown webpages etc. go in here.
|
||||
- <code>$DWEB_ROOT/bin/</code>: custom handlers go here.
|
||||
|
||||
Run <code>build</code> in <code>$DWEB_ROOT/src</code> to recompile the website software.
|
||||
|
||||
Source
|
||||
--------
|
||||
|
||||
You can get the source code on [github](https://github.com/j3parker/dweb) or by running
|
||||
|
||||
git clone git://github.com/j3parker/Go-OpenGL.git
|
||||
|
||||
Contact
|
||||
--------
|
||||
For questions, suggestions, bug reports and contributing patches email [j3parker](mailto:j3parker@csclub.uwaterloo.ca)
|
||||
|
||||
License
|
||||
-------
|
||||
Public domain.
|
||||
|
||||
Credits
|
||||
-------
|
||||
The idea and css stolen from [werc][werc]. This page itself also plagarised.
|
||||
|
||||
Thanks to John Gruber for the [Markdown.pl][md] script.
|
Loading…
Reference in New Issue