From f5f491059254241520cf4cfd52b7f9b74ebf1ebd Mon Sep 17 00:00:00 2001 From: "Roi Martin (@nibble_ds)" Date: Thu, 6 Feb 2014 10:54:27 +0100 Subject: [PATCH] Initial commit --- .gitignore | 1 + Makefile | 17 ++ README | 40 +++++ md2html.awk | 427 ++++++++++++++++++++++++++++++++++++++++++++++++++ style.css | 87 ++++++++++ style.old.css | 209 ++++++++++++++++++++++++ sw | 106 +++++++++++++ sw.conf.def | 9 ++ whereis | 9 ++ 9 files changed, 905 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 README create mode 100755 md2html.awk create mode 100644 style.css create mode 100644 style.old.css create mode 100755 sw create mode 100644 sw.conf.def create mode 100755 whereis diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1377554 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.swp diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3f241a5 --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ +# sw - suckless webframework - 2012 - MIT License - nibble + +DESTDIR?= +PREFIX?=/usr/local +P=${DESTDIR}/${PREFIX} + +all: sw.conf + +sw.conf: + cp sw.conf.def sw.conf + +install: + mkdir -p ${P}/bin + sed -e "s,/usr/bin/awk,`./whereis awk`,g" md2html.awk > ${P}/bin/md2html.awk + chmod +x ${P}/bin/md2html.awk + cp -f sw ${P}/bin/sw + chmod +x ${P}/bin/sw diff --git a/README b/README new file mode 100644 index 0000000..11c3db7 --- /dev/null +++ b/README @@ -0,0 +1,40 @@ +sw - suckless webframework +========================== +sw is a minimal and sane web framework. + +Installation +------------ +Run: + make && make install PREFIX=/usr/local + +Configuration +------------- +Copy sw.conf and style.css to your working directory, and edit them to fit your needs. + +Static web generation +--------------------- +Run from your working directory: + sw /path/to/site + +Where 'site' is the folder where your website is located. +The static version of the website is created under 'site.static'. + +Automatic generation+upload +--------------------------- +The whole process can be automatized if you create a Makefile like this in your working directory: + +$ cat Makefile +all: + sw /path/to/site + rsync -avz site.static/ foo.org:/path/to/wwwroot/ +clean: + rm -rf site.static + +Author +------ +Nibble + +Contributors +------------ +pancake +Andrew Antle diff --git a/md2html.awk b/md2html.awk new file mode 100755 index 0000000..6ab84bf --- /dev/null +++ b/md2html.awk @@ -0,0 +1,427 @@ +#!/usr/bin/awk -f +# +# by: Jesus Galan (yiyus) 2009 +# +# Usage: md2html.awk file.md > file.html +# See: http://4l77.com/src/md2html.awk + +function eschtml(t) { + gsub("&", "\\&", t); + gsub("<", "\\<", t); + return t; +} + +function oprint(t){ + if(nr == 0) + print t; + else + otext = otext "\n" t; +} + +function subref(id){ + for(; nr > 0 && sub("<<" id, ref[id], otext); nr--); + if(nr == 0 && otext) { + print otext; + otext = ""; + } +} + +function nextil(t) { + if(!match(t, /[`<&\[*_\\-]|(\!\[)/)) + return t; + t1 = substr(t, 1, RSTART - 1); + tag = substr(t, RSTART, RLENGTH); + t2 = substr(t, RSTART + RLENGTH); + if(ilcode && tag != "`") + return eschtml(t1 tag) nextil(t2); + # Backslash escaping + if(tag == "\\"){ + if(match(t2, /^[\\`*_{}\[\]()#+\-\.!]/)){ + tag = substr(t2, 1, 1); + t2 = substr(t2, 2); + } + return t1 tag nextil(t2); + } + # Dashes + if(tag == "-"){ + if(sub(/^-/, "", t2)) + tag = "—"; + return t1 tag nextil(t2); + } + # Inline Code + if(tag == "`"){ + if(sub(/^`/, "", t2)){ + if(!match(t2, /``/)) + return t1 "”" nextil(t2); + ilcode2 = !ilcode2; + } + else if(ilcode2) + return t1 tag nextil(t2); + tag = ""; + if(ilcode){ + t1 = eschtml(t1); + tag = ""; + } + ilcode = !ilcode; + return t1 tag nextil(t2); + } + if(tag == "<"){ + # Autolinks + if(match(t2, /^[^ ]+[\.@][^ ]+>/)){ + url = eschtml(substr(t2, 1, RLENGTH - 1)); + t2 = substr(t2, RLENGTH + 1); + linktext = url; + if(match(url, /@/) && !match(url, /^mailto:/)) + url = "mailto:" url; + return t1 "" linktext "" nextil(t2); + } + # Html tags + if(match(t2, /^[A-Za-z\/!][^>]*>/)){ + tag = tag substr(t2, RSTART, RLENGTH); + t2 = substr(t2, RLENGTH + 1); + return t1 tag nextil(t2); + } + return t1 "<" nextil(t2); + } + # Html special entities + if(tag == "&"){ + if(match(t2, /^#?[A-Za-z0-9]+;/)){ + tag = tag substr(t2, RSTART, RLENGTH); + t2 = substr(t2, RLENGTH + 1); + return t1 tag nextil(t2); + } + return t1 "&" nextil(t2); + } + # Images + if(tag == "!["){ + if(!match(t2, /(\[.*\])|(\(.*\))/)) + return t1 tag nextil(t2); + match(t2, /^[^\]]*/); + alt = substr(t2, 1, RLENGTH); + t2 = substr(t2, RLENGTH + 2); + if(match(t2, /^\(/)){ + # Inline + sub(/^\(/, "", t2); + match(t2, /^[^\)]+/); + url = eschtml(substr(t2, 1, RLENGTH)); + t2 = substr(t2, RLENGTH + 2); + title = ""; + if(match(url, /[ ]+\".*\"[ ]*$/)) { + title = substr(url, RSTART, RLENGTH); + url = substr(url, 1, RSTART - 1); + match(title, /\".*\"/); + title = " title=\"" substr(title, RSTART + 1, RLENGTH - 2) "\""; + } + if(match(url, /^<.*>$/)) + url = substr(url, 2, RLENGTH - 2); + return t1 "\""" nextil(t2); + } + else{ + # Referenced + sub(/^ ?\[/, "", t2); + id = alt; + if(match(t2, /^[^\]]+/)) + id = substr(t2, 1, RLENGTH); + t2 = substr(t2, RLENGTH + 2); + if(ref[id]) + r = ref[id]; + else{ + r = "<<" id; + nr++; + } + return t1 "\""" nextil(t2); + } + } + # Links + if(tag == "["){ + if(!match(t2, /(\[.*\])|(\(.*\))/)) + return t1 tag nextil(t2); + match(t2, /^[^\]]*(\[[^\]]*\][^\]]*)*/); + linktext = substr(t2, 1, RLENGTH); + t2 = substr(t2, RLENGTH + 2); + if(match(t2, /^\(/)){ + # Inline + match(t2, /^[^\)]+(\([^\)]+\)[^\)]*)*/); + url = substr(t2, 2, RLENGTH - 1); + pt2 = substr(t2, RLENGTH + 2); + title = ""; + if(match(url, /[ ]+\".*\"[ ]*$/)) { + title = substr(url, RSTART, RLENGTH); + url = substr(url, 1, RSTART - 1); + match(title, /\".*\"/); + title = " title=\"" substr(title, RSTART + 1, RLENGTH - 2) "\""; + } + if(match(url, /^<.*>$/)) + url = substr(url, 2, RLENGTH - 2); + url = eschtml(url); + return t1 "" nextil(linktext) "" nextil(pt2); + } + else{ + # Referenced + sub(/^ ?\[/, "", t2); + id = linktext; + if(match(t2, /^[^\]]+/)) + id = substr(t2, 1, RLENGTH); + t2 = substr(t2, RLENGTH + 2); + if(ref[id]) + r = ref[id]; + else{ + r = "<<" id; + nr++; + } + pt2 = t2; + return t1 "" nextil(linktext) "" nextil(pt2); + } + } + # Emphasis + if(match(tag, /[*_]/)){ + ntag = tag; + if(sub("^" tag, "", t2)){ + if(stag[ns] == tag && match(t2, "^" tag)) + t2 = tag t2; + else + ntag = tag tag + } + n = length(ntag); + tag = (n == 2) ? "strong" : "em"; + if(match(t1, / $/) && match(t2, /^ /)) + return t1 tag nextil(t2); + if(stag[ns] == ntag){ + tag = "/" tag; + ns--; + } + else + stag[++ns] = ntag; + tag = "<" tag ">"; + return t1 tag nextil(t2); + } +} + +function inline(t) { + ilcode = 0; + ilcode2 = 0; + ns = 0; + + return nextil(t); +} + +function printp(tag) { + if(!match(text, /^[ ]*$/)){ + text = inline(text); + if(tag != "") + oprint("<" tag ">" text ""); + else + oprint(text); + } + text = ""; +} + +BEGIN { + blank = 0; + code = 0; + hr = 0; + html = 0; + nl = 0; + nr = 0; + otext = ""; + text = ""; + par = "p"; +} + +# References +!code && /^ *\[[^\]]*\]:[ ]+/ { + sub(/^ *\[/, ""); + match($0, /\]/); + id = substr($0, 1, RSTART - 1); + sub(id "\\]:[ ]+", ""); + title = ""; + if(match($0, /\".*\"$/)) + title = "\" title=\"" substr($0, RSTART + 1, RLENGTH - 2); + sub(/[ ]+\".*\"$/, ""); + url = eschtml($0); + ref[id] = url title; + + subref(id); + next; +} + +# html +!html && /^<(address|blockquote|center|dir|div|dl|fieldset|form|h[1-6r]|\ +isindex|menu|noframes|noscript|ol|p|pre|table|ul|!--)/ { + if(code) + oprint(""); + for(; !text && block[nl] == "blockquote"; nl--) + oprint(""); + match($0, /^<(address|blockquote|center|dir|div|dl|fieldset|form|h[1-6r]|\ + isindex|menu|noframes|noscript|ol|p|pre|table|ul|!--)/); + htag = substr($0, 2, RLENGTH - 1); + if(!match($0, "(<\\/" htag ">)|((^
$)")) + html = 1; + if(html && match($0, /^
$/ || +(hr && />$/)) { + html = 0; + hr = 0; + oprint($0); + next; +} + +html { + oprint($0); + next; +} + +# List and quote blocks + +# Remove indentation +{ + for(nnl = 0; nnl < nl; nnl++) + if((match(block[nnl + 1], /[ou]l/) && !sub(/^( | )/, "")) || \ + (block[nnl + 1] == "blockquote" && !sub(/^> ?/, ""))) + break; +} +nnl < nl && !blank && text && ! /^ ? ? ?([*+-]|([0-9]+\.)+)( +| )/ { nnl = nl; } +# Quote blocks +{ + while(sub(/^> /, "")) + nblock[++nnl] = "blockquote"; +} +# Horizontal rules +{ hr = 0; } +(blank || (!text && !code)) && /^ ? ? ?([-*_][ ]*)([-*_][ ]*)([-*_][ ]*)+$/ { + if(code){ + oprint(""); + code = 0; + } + blank = 0; + nnl = 0; + hr = 1; +} +# List items +block[nl] ~ /[ou]l/ && /^$/ { + blank = 1; + next; +} +{ newli = 0; } +!hr && (nnl != nl || !text || block[nl] ~ /[ou]l/) && /^ ? ? ?[*+-]( +| )/ { + sub(/^ ? ? ?[*+-]( +| )/, ""); + nnl++; + nblock[nnl] = "ul"; + newli = 1; +} +(nnl != nl || !text || block[nl] ~ /[ou]l/) && /^ ? ? ?([0-9]+\.)+( +| )/ { + sub(/^ ? ? ?([0-9]+\.)+( +| )/, ""); + nnl++; + nblock[nnl] = "ol"; + newli = 1; +} +newli { + if(blank && nnl == nl && !par) + par = "p"; + blank = 0; + printp(par); + if(nnl == nl && block[nl] == nblock[nl]) + oprint("
  • "); +} +blank && ! /^$/ { + if(match(block[nnl], /[ou]l/) && !par) + par = "p"; + printp(par); + par = "p"; + blank = 0; +} + +# Close old blocks and open new ones +nnl != nl || nblock[nl] != block[nl] { + if(code){ + oprint(""); + code = 0; + } + printp(par); + b = (nnl > nl) ? nblock[nnl] : block[nnl]; + par = (match(b, /[ou]l/)) ? "" : "p"; +} +nnl < nl || (nnl == nl && nblock[nl] != block[nl]) { + for(; nl > nnl || (nnl == nl && pblock[nl] != block[nl]); nl--){ + if(match(block[nl], /[ou]l/)) + oprint("
  • "); + oprint(""); + } +} +nnl > nl { + for(; nl < nnl; nl++){ + block[nl + 1] = nblock[nl + 1]; + oprint("<" block[nl + 1] ">"); + if(match(block[nl + 1], /[ou]l/)) + oprint("
  • "); + } +} +hr { + oprint("
    "); + next; +} + +# Code blocks +code && /^$/ { + if(blanK) + oprint(""); + blank = 1; + next; +} +!text && sub(/^( | )/, "") { + if(blanK) + oprint(""); + blank = 0; + if(!code) + oprint("
    ");
    +	code = 1;
    +	$0 = eschtml($0);
    +	oprint($0);
    +	next;
    +}
    +code {
    +	oprint("
    "); + code = 0; +} + +# Setex-style Headers +text && /^=+$/ {printp("h1"); next;} +text && /^-+$/ {printp("h2"); next;} + +# Atx-Style headers +/^#+/ && (!newli || par=="p" || /^##/) { + for(n = 0; n < 6 && sub(/^# */, ""); n++) + sub(/#$/, ""); + par = "h" n; +} + +# Paragraph +/^$/ { + printp(par); + par = "p"; + next; +} + +# Add text +{ text = (text ? text " " : "") $0; } + +END { + if(code){ + oprint(""); + code = 0; + } + printp(par); + for(; nl > 0; nl--){ + if(match(block[nl], /[ou]l/)) + oprint("
  • "); + oprint(""); + } + gsub(/<<[^\"]*/, "", otext); + print(otext); +} diff --git a/style.css b/style.css new file mode 100644 index 0000000..03eb739 --- /dev/null +++ b/style.css @@ -0,0 +1,87 @@ +/* Based on werc.cat-v.org, suckless.org and garbe.us */ + +/* General */ +body { + color: #aaa; + font-family: sans-serif; + font-size: 80%; + margin: 0; + padding: 0 +} + +/* Header */ +.header { background-color: #ccc; border: 0; } +.header a { border: 0; color: #111; text-decoration: none; } +.midHeader img { border: 0; } + +.headerTitle { font-size: 1.6em; font-weight: bold; margin: 0 0 0 0.5em; padding: 0.5em; } +.headerTitle a { border: 0; text-decoration: none; } + +.headerSubTitle { font-size: 0.6em; font-weight: normal; margin-left: 1em; } + +/* Side */ +#side-bar { + width: 100%; + clear: both; + border: 0; + margin: 0; + padding: 0; + background-color: #ddd; +} + +#side-bar ul { + margin: 0; + padding: 0.3em; + list-style-type: none; + list-style-image: none; + border: 0; +} + +#side-bar li { display: inline; line-height: 1.6em; white-space: nowrap; } + +#side-bar ul li a { + margin: 0; + padding: 0.1em 1ex 0.1em 1ex; + color: #336699; + background-color: transparent; + text-decoration: none; + font-size: 1em; + border: 0; +} + +#side-bar ul li a:hover { color: #111; text-decoration: none; } + +/* Main Copy */ +#main { + max-width: 70em; + color: #111; + margin: 0 auto 0 2em; + padding: 1em 3em 2em 1em; + border: 0; +} + +#main a { color: #336699; text-decoration: none; } +#main a:hover { text-decoration: underline; } +#main h1, #main-copy h2 { color: #666; } +#main ul { list-style-type: square; } + +/* Footer */ +#footer { + background-color: #ddd; + color: #111; + font-size: 91%; + padding: 2em; + clear: both; +} + +#footer .left { text-align: left; float: left; clear: left; } +#footer .right { text-align: right; } +#footer a { color: #111; text-decoration: none; } +#footer a:hover { text-decoration: underline; } + +abbr, acronym { border-bottom: 1px dotted #333; cursor: help; } +blockquote { border-left: 1px solid #333; font-style: italic; padding: 1em; } +hr { border-width: 0 0 0.1em 0; border-color: #666; } + +code, pre { font-size: 1.1em } +pre { margin-left: 2em; } diff --git a/style.old.css b/style.old.css new file mode 100644 index 0000000..a049b4c --- /dev/null +++ b/style.old.css @@ -0,0 +1,209 @@ +/* Based on werc stylesheet (werc.cat-v.org) */ + +/* Header */ +.header { + 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; } + +/* Side */ +#side-bar { + width: 16em; + float: left; + clear: left; + border-right: 1px solid #ddd; +} + +#side-bar ul { + list-style-type: none; + list-style-position: outside; + margin: 0; + padding: 0 0 0.3em 0; +} + +#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; +} + +#side-bar a:hover { + color: white; + background-color: rgb(100,135,220); + border-left: black solid 0.2em; + text-decoration: none; +} + +/* Main Copy */ +#main { + 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 p { + margin: 1em 1ex 1em 1ex !important; /* Need !important so troff-generated pages don't look totally squezed */ + padding: 0; +} + +#main a { + color: rgb(0,102,204); + background-color: transparent; +} + +#main a:hover { + color: rgb(100,135,220); +} + +#main h1, #main 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 h2 { + font-size: 115.5%; + border-bottom: 1px solid rgb(0,102,204); +} + +#main .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: 0.4em; + clear: both; +} + +#footer .right { + text-align: right; + line-height: 1.45em; +} + +#footer a { + color: white; + background-color: transparent; +} + +/* General */ +body { + color: black; + background-color: white; + font-family: Helvetica, Arial, 'Liberation Sans', FreeSans, sans-serif; + font-size: 84%; /* Enables font size scaling in MSIE */ + margin: 0; + padding: 0; +} + +a { text-decoration: none; } +a:hover { text-decoration: underline; } + +li ul { + padding-left: 0.6em !important; +} + +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; +} diff --git a/sw b/sw new file mode 100755 index 0000000..4f57bff --- /dev/null +++ b/sw @@ -0,0 +1,106 @@ +#!/bin/sh +# sw - suckless webframework - 2012 - MIT License - nibble + +sw_filter() { + for b in $BL; do + [ "$b" = "$1" ] && return 0 + done +} + +sw_main() { + $MDHANDLER $1 +} + +sw_menu() { + echo "
      " + [ -z "`echo $1 | grep index.md`" ] && echo "
    • .
    • " + [ "`dirname $1`" != "." ] && echo "
    • ..
    • " + FILES=`ls \`dirname $1\` | sed -e 's,.md$,.html,g'` + for i in $FILES ; do + sw_filter $i && continue + NAME=`echo $i | sed -e 's/\..*$//' -e 's/_/ /g'` + [ -z "`echo $i | grep '\..*$'`" ] && i="$i/index.html" + echo "
    • $NAME
    • " + done + echo "
    " +} + +sw_page() { + # Header + cat << _header_ + + + +${TITLE} + + +_header_ + # Stylesheet + sw_style + cat << _header_ + + +
    +

    +${TITLE} ${SUBTITLE} +

    +
    +_header_ + # Menu + echo "
    " + sw_menu $1 + echo "
    " + # Body + echo "
    " + sw_main $1 + echo "
    " + # Footer + cat << _footer_ + + + +_footer_ +} + +sw_style() { + if [ -f $CDIR/$STYLE ]; then + echo '' + fi +} + +# Set input dir +IDIR="`echo $1 | sed -e 's,/*$,,'`" +if [ -z "$IDIR" ] || [ ! -d $IDIR ]; then + echo "Usage: sw [dir]" + exit 1 +fi + +# Load config file +if [ ! -f $PWD/sw.conf ]; then + echo "Cannot find sw.conf in current directory" + exit 1 +fi +. $PWD/sw.conf + +# Setup output dir structure +CDIR=$PWD +ODIR="$CDIR/`basename $IDIR`.static" +rm -rf $ODIR +mkdir -p $ODIR +cp -rf $IDIR/* $ODIR +rm -f `find $ODIR -type f -iname '*.md'` + +# Parse files +cd $IDIR +FILES=`find . -iname '*.md' | sed -e 's,^\./,,'` +for a in $FILES; do + b="$ODIR/`echo $a | sed -e 's,.md$,.html,g'`" + echo "* $a" + sw_page $a > $b; +done + +exit 0 diff --git a/sw.conf.def b/sw.conf.def new file mode 100644 index 0000000..385c2c9 --- /dev/null +++ b/sw.conf.def @@ -0,0 +1,9 @@ +# sw - suckless webframework - 2012 - nibble + +# Configuration +TITLE="foo.org" # Site title +SUBTITLE="" # Site subtitle +BL="index.html images" # Black list +STYLE="style.css" # Stylesheet name +# External apps +MDHANDLER="/usr/local/bin/md2html.awk" # md handler diff --git a/whereis b/whereis new file mode 100755 index 0000000..9cf5412 --- /dev/null +++ b/whereis @@ -0,0 +1,9 @@ +#!/bin/sh +[ -z "$1" ] && exit 1 +IFS=: +for a in $PATH ; do + if [ -e "$a/$1" ]; then + echo "$a/$1" + break + fi +done