swerc

anselm's simpler werc fork
git clone git://git.suckless.org/swerc
Log | Files | Refs | README

commit 32beaba137cab07ab4b72e8faeb3cbcbb5031811
parent 2e3041676a90f105a3c9162c8ce7d04413383b16
Author: anselm@garbe.us <unknown>
Date:   Sun, 12 Feb 2012 18:43:06 +0100

merged anselms branch
Diffstat:
MREADME | 52++++++++++++----------------------------------------
Dbin/aux/addwuser.rc | 33---------------------------------
Dbin/aux/bpst.rc | 64----------------------------------------------------------------
Dbin/aux/gensitemaptxt.rc | 14--------------
Dbin/aux/runtsts.rc | 16----------------
Dbin/cgilib.rc | 232-------------------------------------------------------------------------------
Dbin/contrib/hgweb.config | 12------------
Dbin/contrib/hgwebdir.cgi | 47-----------------------------------------------
Dbin/contrib/markdown.pl | 1447-------------------------------------------------------------------------------
Dbin/contrib/md2html.awk | 427-------------------------------------------------------------------------------
Dbin/contrib/urldecode.awk | 39---------------------------------------
Dbin/contrib/urlencode.awk | 126-------------------------------------------------------------------------------
Dbin/contrib/webserver.rc | 30------------------------------
Dbin/corehandlers.rc | 157-------------------------------------------------------------------------------
Mbin/fltr_cache.rc | 0
Abin/handlers.rc | 106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abin/util.rc | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mbin/werc.rc | 31++++++++-----------------------
Dbin/werc_errlog_wrap.rc | 5-----
Dbin/wercconf.rc | 19-------------------
Dbin/werclib.rc | 148-------------------------------------------------------------------------------
Metc/initrc | 41++++-------------------------------------
Detc/users/GROUP_AND_USER_ACCOUNTS | 1-
Dlib/404.tpl | 12------------
Dlib/default_master.tpl | 35-----------------------------------
Dlib/footer.inc | 6------
Dlib/headers.tpl | 29-----------------------------
Dlib/top_bar.inc | 16----------------
Dpub/default_favicon.ico | 0
Apub/style.css | 155+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dpub/style/imgs/sgl.png | 0
Dpub/style/sinorca-screen-alt.css | 293-------------------------------------------------------------------------------
Dpub/style/style.css | 330-------------------------------------------------------------------------------
Dpub/style/style_old.css | 330-------------------------------------------------------------------------------
Apub/style1.css | 156+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsites/CREATE-SITE-DIRECTORIES-HERE | 0
Dsites/default.cat-v.org/_werc/lib/footer.inc | 29-----------------------------
Dsites/default.cat-v.org/_werc/lib/headers.inc | 5-----
Dsites/default.cat-v.org/_werc/lib/top_bar.inc | 25-------------------------
Dsites/tst.cat-v.org/_werc/config | 2--
Dsites/tst.cat-v.org/apps/blagh/_werc/config | 3---
Dsites/tst.cat-v.org/apps/bridge/a/_werc/config | 1-
Dsites/tst.cat-v.org/index.md | 4----
Dsites/tst.cat-v.org/titles/dashed-title.md | 3---
Dsites/tst.cat-v.org/titles/under_title.md | 3---
Dsites/werc.cat-v.org/_werc/config | 7-------
Dsites/werc.cat-v.org/apps/_footer.md | 10----------
Dsites/werc.cat-v.org/apps/_header.md | 5-----
Dsites/werc.cat-v.org/apps/blagh/index.md | 59-----------------------------------------------------------
Dsites/werc.cat-v.org/apps/bridge/index.md | 13-------------
Dsites/werc.cat-v.org/apps/dirdir/index.md | 48------------------------------------------------
Dsites/werc.cat-v.org/apps/wman/index.md | 34----------------------------------
Dsites/werc.cat-v.org/development/index.md | 21---------------------
Dsites/werc.cat-v.org/development/roadmap.md | 62--------------------------------------------------------------
Dsites/werc.cat-v.org/development/todo.md | 88-------------------------------------------------------------------------------
Dsites/werc.cat-v.org/docs/_werc/config | 1-
Dsites/werc.cat-v.org/docs/config-options.md | 68--------------------------------------------------------------------
Dsites/werc.cat-v.org/docs/css-style.md | 18------------------
Dsites/werc.cat-v.org/docs/dir-listings.md | 29-----------------------------
Dsites/werc.cat-v.org/docs/rc-template-lang.md | 56--------------------------------------------------------
Dsites/werc.cat-v.org/docs/site-customization.md | 53-----------------------------------------------------
Dsites/werc.cat-v.org/docs/user-management.md | 36------------------------------------
Dsites/werc.cat-v.org/docs/web-server-setup/_header.md | 16----------------
Dsites/werc.cat-v.org/docs/web-server-setup/apache.md | 93-------------------------------------------------------------------------------
Dsites/werc.cat-v.org/docs/web-server-setup/cherokee.md | 31-------------------------------
Dsites/werc.cat-v.org/docs/web-server-setup/hiawatha.md | 16----------------
Dsites/werc.cat-v.org/docs/web-server-setup/lighttpd.md | 44--------------------------------------------
Dsites/werc.cat-v.org/docs/web-server-setup/nginx.md | 96-------------------------------------------------------------------------------
Dsites/werc.cat-v.org/docs/web-server-setup/nhttpd.md | 60------------------------------------------------------------
Dsites/werc.cat-v.org/docs/web-server-setup/plan-9-httpd.md | 53-----------------------------------------------------
Dsites/werc.cat-v.org/index.md | 104-------------------------------------------------------------------------------
Dsites/werc.cat-v.org/testimonials.md | 8--------
Dsites/werc.cat-v.org/wiki/_werc/config | 1-
Atpl/404.tpl | 3+++
Dtpl/_debug.tpl | 29-----------------------------
Dtpl/_users/login.tpl | 18------------------
Atpl/master.tpl | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtpl/sitemap.tpl | 3---
78 files changed, 631 insertions(+), 5223 deletions(-)

diff --git a/README b/README @@ -1,12 +1,7 @@ -werc - a minimalist document management system ----------------------------------------------- - -Werc is a content management system and web (anti-)framework designed to be simple to -use, simple to setup, simple to hack on, and not get on the way while allowing -users easy customization. - -For more information see the official website: http://werc.cat-v.org/ +swerc - a minimalist document management system +----------------------------------------------- +swerc is simple werc, a fork of Uriel's werc at: http://werc.cat-v.org/ Installation ------------ @@ -14,9 +9,10 @@ Installation Requirements: * An http server that can handle CGIs -* Plan 9 from User Space: http://plan9.us - Or 9base-5 or later: http://tools.suckless.org/9base +* Plan 9 from User Space: http://plan9.us - Or http://tools.suckless.org/9base +* discount markdown: http://www.pell.portland.or.us/~orc/Code/discount/ -Note: Werc by default expects the Plan 9 tools to be installed under +Note: swerc by default expects the Plan 9 tools to be installed under /usr/local/plan9/bin/, if you have installed them elsewhere you will need to edit the #! line in bin/werc.rc and customize the $plan9port variable in your etc/initrc.local. @@ -24,7 +20,7 @@ etc/initrc.local. Instructions: -Untar werc at your desired location, configure httpd to use +Untar swerc at your desired location, configure httpd to use /path-to-your-werc-installation/bin/werc.rc as a cgi-script, it is recommended that you make werc.rc handle all non-static files (this can be done by setting it up as your 404 handler) and setup your virtual hosts to handle static files @@ -42,40 +38,16 @@ standard /usr/local/plan9/ you will need to edit the first line of bin/werc.rc (Note that p9p is picky about where it is located, once you run ./INSTALL you should *not* move it to a different directory without running ./INSTALL again.) -For general configuration options copy etc/initrc to etc/initrc.local and -customize it as needed. Site (and directory) specific options can be set in a -sites/example.com/_werc/config file inside the site's directory. To customize -templates and included files you can store your own version of the files in -lib/ under sites/example.com/_werc/lib - -The source tree for the werc website is included under sites/werc.cat-v.org as -an example, feel free to use it as a template for your own site. - -For more details see the documentation section of the website: -http://werc.cat-v.org/docs/ - - -Contact -------- - -For comments, suggestions, bug reports or patches join the werc9 list in -google groups: http://groups.google.com/group/werc9 or the irc channel #plan9 -in irc.freenode.org - -If you have a public website that uses werc I would love to hear about it and -get feedback about you experience setting it up. - -If you want to be notified of new releases see the News section of the website -or use Freshmeat: http://freshmeat.net/projects/werc/ +For general configuration edit etc/initrc. +Site (and directory) specific options can be set in a +sites/example.com/_werc/config file inside the site's directory. Thanks ------ -Garbeam, Kris Maglione, sqweek, soul9, mycroftiv, maht, yiyus and many others +Kris Maglione, sqweek, soul9, mycroftiv, maht, yiyus and many others for their ideas, patches, testing and other contributions. - License ------- - -Werc is in the public domain. +swerc is in the public domain. diff --git a/bin/aux/addwuser.rc b/bin/aux/addwuser.rc @@ -1,33 +0,0 @@ -#!/usr/bin/env rc - -if(! ~ $#werc_root 0) - cd $werc_root - -fn usage { - if(! ~ $#* 0) - echo $0: $* >[1=2] - echo 'Usage:' $0 'user_name user_password [groups ...]' >[1=2] - exit usage -} - -if(! test -d etc/users/) - usage 'Run for root of werc installation or set $werc_root' - -user_name=$1 -shift -user_pass=$1 -shift -user_groups=$* - -if(~ $"user_name '' || ~ $"user_pass '') - usage - -mkdir etc/users/$user_name -echo $user_pass > etc/users/$user_name/password - -if(! ~ $#user_groups 0) - for(g in $user_groups) { - mkdir -p etc/users/$g - echo $user_name >> etc/users/$g/members - } - diff --git a/bin/aux/bpst.rc b/bin/aux/bpst.rc @@ -1,64 +0,0 @@ -#!/usr/bin/env rc - -path=( $PLAN9/bin $path ) -base=. - -if(~ $#user 0) - user=`{whoami} - -file=(); title=(); -bloguser=$user -while(! ~ $#* 0) { - switch($1) { - case -u - base=/gsoc/www/people/$user/blog/ - case -b - shift - base=$1 - case -f - shift - file=$1 - } - shift -} - -if(~ $"EDITOR '') - EDITOR=vi - -if(~ $#file 0 || ! test -f $file) { - file=/tmp/blogtmp.$pid - rm $file >[2]/dev/null - touch $file -} - -$EDITOR $file -ispell $file -rm $file.bak >[2]/dev/null - -fn mkbpost { - umask 002 # Let group write - bptext=$1 - if(! ~ $#2 0) - bpid=`{echo -n '-'^$"bpid | sed 's/'$forbidden_uri_chars'+/_/g; 1q'} - d=`{/bin/date +%F|sed 's,-,/,g'} - - ddir=$blagh_root^$d^'/' - n=`{ls $ddir >[2]/dev/null |wc -l} - - mkdir -p $ddir/$"n^$"bpid/ - { - # TODO: Enable metadata - #echo '* Posted:' `{date} - #if(! ~ $#logged_user 0) - # echo '* Author: '$logged_user - cat $bptext - }> $ddir/$"n^$"bpid/index.md -} - -forbidden_uri_chars='[^a-zA-Z0-9_+\-\/\.]' -blagh_root=$base - -if(test -s $file) - mkbpost $file -if not - echo Empty file! diff --git a/bin/aux/gensitemaptxt.rc b/bin/aux/gensitemaptxt.rc @@ -1,14 +0,0 @@ -#!/usr/bin/env rc -# DEPRECATED: sitemap.tpl now generates and updates a sitemap.txt when requested, and is also more smart than this simplistic script. - -for(d in sites/*/) { -echo $d -9 du -a $d | awk '/\.(md|html)$/ { print $2 }; {}' | 9 sed -e 's/\.(md|html)$//' -e 's,/index$,/,' -e 's,^sites/,http://,' > $d/sitemap.txt - -if(! test -f $d/robots.txt) { - echo generating missing robots.txt for $d - echo $d|sed 's,sites/,Sitemap: http://,; s/$/sitemap.txt/;' > $d/robots.txt - cat $d/robots.txt -} - -} diff --git a/bin/aux/runtsts.rc b/bin/aux/runtsts.rc @@ -1,16 +0,0 @@ -#!/usr/bin/env rc - -tstdom='http://test.cat-v.org' - -cd sites/tst.cat-v.org - -tstfiles=`{du -a |awk '/\.tst$/ { print $2 }; {} ' | sed 's/^\.//; s/\.tst$//'} - -for(f in $tstfiles) { - ifs=' -' { tsts=`{cat ./$f.tst} } - - for(t in $tsts) { - echo tst $t - } -} diff --git a/bin/cgilib.rc b/bin/cgilib.rc @@ -1,232 +0,0 @@ -# Useful CGI stuff - -fn dprint { echo $* >[1=2] } -fn dprintv { { for(v in $*) { echo -n $v^'#'^$#$v^'=' $$v '; ' }; echo } >[1=2] } - -fn escape_html { sed 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g' $* } - -fn http_redirect { - if(~ $1 http://* https://*) - t=$1 - if not if(~ $1 /*) - t=$"base_url^$1 - if not - t=$"base_url^$"req_path^$1 - echo 'Status: '^$2^' -Location: '^$t^' - -' - exit -} -fn perm_redirect { http_redirect $1 '301 Moved Permanantly' } -fn post_redirect { http_redirect $1 '303 See Other' } - - -# Note: should check if content type is application/x-www-form-urlencoded? -# Should compare with http://www.shelldorado.com/scripts/cmds/urlgetopt.txt -fn load_post_args { - if(~ $REQUEST_METHOD POST && ~ $#post_args 0) { - ifs='& -' for(pair in `{cat}) { - ifs='=' { pair=`{echo -n $pair} } - n='post_arg_'^`{echo $pair(1)|tr -cd 'a-zA-Z0-9_'} - post_args=( $post_args $n ) - ifs=() { $n=`{echo -n $pair(2)|urldecode|tr -d ' '} } - } - pair=() - } - if not - status='No POST or post args already loaded' -} -# Status is () if at least one arg is found. DEPRECATED: access vars directly. -fn get_post_args { - load_post_args - _status='No post arg matches' - for(n in $*) { - v=post_arg_$n - if(! ~ $#$v 0) { - $n=$$v - _status=() - } - } - status=$_status -} - -# This seems slightly improve performance, but might depend on httpd buffering behavior. -fn awk_buffer { - awk '{ - buf = buf $0"\n" - if(length(buf) > 1400) { - printf "%s", buf - buf = "" - } - } - END { printf "%s", buf }' -} - -fn urldecode { -awk ' -BEGIN { - hextab ["0"] = 0; hextab ["8"] = 8; - hextab ["1"] = 1; hextab ["9"] = 9; - hextab ["2"] = 2; hextab ["A"] = hextab ["a"] = 10 - hextab ["3"] = 3; hextab ["B"] = hextab ["b"] = 11; - hextab ["4"] = 4; hextab ["C"] = hextab ["c"] = 12; - hextab ["5"] = 5; hextab ["D"] = hextab ["d"] = 13; - hextab ["6"] = 6; hextab ["E"] = hextab ["e"] = 14; - hextab ["7"] = 7; hextab ["F"] = hextab ["f"] = 15; -} -{ - decoded = "" - i = 1 - len = length ($0) - while ( i <= len ) { - c = substr ($0, i, 1) - if ( c == "%" ) { - if ( i+2 <= len ) { - c1 = substr ($0, i+1, 1) - c2 = substr ($0, i+2, 1) - if ( hextab [c1] == "" || hextab [c2] == "" ) { - print "WARNING: invalid hex encoding: %" c1 c2 | "cat >&2" - } else { - code = 0 + hextab [c1] * 16 + hextab [c2] + 0 - c = sprintf ("%c", code) - i = i + 2 - } - } else { - print "WARNING: invalid % encoding: " substr ($0, i, len - i) - } - } else if ( c == "+" ) { - c = " " - } - decoded = decoded c - ++i - } - printf "%s", decoded -} -' -} - -fn url_encode { - awk ' - BEGIN { - # We assume an awk implementation that is just plain dumb. - # We will convert an character to its ASCII value with the - # table ord[], and produce two-digit hexadecimal output - # without the printf("%02X") feature. - - EOL = "%0A" # "end of line" string (encoded) - split ("1 2 3 4 5 6 7 8 9 A B C D E F", hextab, " ") - hextab [0] = 0 - for ( i=1; i<=255; ++i ) ord [ sprintf ("%c", i) "" ] = i + 0 - if ("'^$"EncodeEOL^'" == "yes") EncodeEOL = 1; else EncodeEOL = 0 - } - { - encoded = "" - for ( i=1; i<=length ($0); ++i ) { - c = substr ($0, i, 1) - if ( c ~ /[a-zA-Z0-9.-]/ ) { - encoded = encoded c # safe character - } else if ( c == " " ) { - encoded = encoded "+" # special handling - } else { - # unsafe character, encode it as a two-digit hex-number - lo = ord [c] % 16 - hi = int (ord [c] / 16); - encoded = encoded "%" hextab [hi] hextab [lo] - } - } - if ( EncodeEOL ) { - printf ("%s", encoded EOL) - } else { - print encoded - } - } - END { - #if ( EncodeEOL ) print "" - } -' $* -} - -# Cookies -fn set_cookie { - # TODO: should check input values more carefully - name=$1 - val=$2 - extraHttpHeaders=( $extraHttpHeaders 'Set-cookie: '^$"name^'='^$"val^'; path=/;' ) -} -fn get_cookie { - ifs=';' { co=`{echo $HTTP_COOKIE} } - - # XXX: we might be adding a trailing new line? - # The ' ?' is needed to deal with '; ' inter-cookie delimiter - { for(c in $co) echo $c } | sed -n 's/^ ?'$1'=//p' -} - - -fn static_file { - echo 'Content-Type: '`{select_mime $1} - echo - cat $1 - exit -} - -fn select_mime { - m='text/plain' - if(~ $1 *.css) - m='text/css' - if not if(~ $1 *.ico) - m='image/x-icon' - if not if(~ $1 *.png) - m='image/png' - if not if(~ $1 *.jpg *.jpeg) - m='image/jpeg' - if not if(~ $1 *.gif) - m='image/gif' - if not if(~ $1 *.pdf) - m='application/pdf' - echo $m -} - -############################################## -# Generic rc programming helpers - -# Manage nested lists -fn ll_add { - _l=$1^_^$#$1 - $_l=$*(2-) - $1=( $$1 $_l ) -} -# Add to the head: dangerous if you shrink list by hand! -fn ll_addh { - _l=$1^_^$#$1 - $_l=$*(2-) - $1=( $_l $$1 ) -} - - -NEW_LINE=' -' - -# crop_text [max_lenght [ellipsis]] -# TODO: Option to crop only at word-delimiters. -fn crop_text { - m=512 - e='...' - if(! ~ $#1 0) - m=$1 - if(! ~ $#2 0) - e=$2 - - awk -v 'max='^$"m -v 'ellipsis='$e ' - { - nc += 1 + length; - if(nc > max) { - print substr($0, 1, nc - max) " " ellipsis - exit - } - print - }' -} - - diff --git a/bin/contrib/hgweb.config b/bin/contrib/hgweb.config @@ -1,12 +0,0 @@ -[web] -style = gitweb -allow_archive = bz2 - -#[paths] -#w9 = /gsoc/hg/w9/ - -[collections] -#allow_archive = bz2 zip -/gsoc/hg = /gsoc/hg/ -#/var/hg = /var/hg/ - diff --git a/bin/contrib/hgwebdir.cgi b/bin/contrib/hgwebdir.cgi @@ -1,47 +0,0 @@ -#!/usr/bin/env python -# -# An example CGI script to export multiple hgweb repos, edit as necessary - -# send python tracebacks to the browser if an error occurs: -import cgitb -cgitb.enable() - -# adjust python path if not a system-wide install: -#import sys -#sys.path.insert(0, "/path/to/python/lib") - -# If you'd like to serve pages with UTF-8 instead of your default -# locale charset, you can do so by uncommenting the following lines. -# Note that this will cause your .hgrc files to be interpreted in -# UTF-8 and all your repo files to be displayed using UTF-8. -# -#import os -#os.environ["HGENCODING"] = "UTF-8" - -from mercurial.hgweb.hgwebdir_mod import hgwebdir -from mercurial.hgweb.request import wsgiapplication -import mercurial.hgweb.wsgicgi as wsgicgi - -# The config file looks like this. You can have paths to individual -# repos, collections of repos in a directory tree, or both. -# -# [paths] -# virtual/path = /real/path -# virtual/path = /real/path -# -# [collections] -# /prefix/to/strip/off = /root/of/tree/full/of/repos -# -# collections example: say directory tree /foo contains repos /foo/bar, -# /foo/quux/baz. Give this config section: -# [collections] -# /foo = /foo -# Then repos will list as bar and quux/baz. -# -# Alternatively you can pass a list of ('virtual/path', '/real/path') tuples -# or use a dictionary with entries like 'virtual/path': '/real/path' - -def make_web_app(): - return hgwebdir("hgweb.config") - -wsgicgi.launch(wsgiapplication(make_web_app)) diff --git a/bin/contrib/markdown.pl b/bin/contrib/markdown.pl @@ -1,1447 +0,0 @@ -#!/usr/bin/env perl -# -# Markdown -- A text-to-HTML conversion tool for web writers -# -# Copyright (c) 2004 John Gruber -# <http://daringfireball.net/projects/markdown/> -# -package Markdown; -require 5.006_000; -use strict; -use warnings; - -use Digest::MD5 qw(md5_hex); -use vars qw($VERSION); -$VERSION = '1.0.1'; -# Tue 14 Dec 2004 - -## Disabled; causes problems under Perl 5.6.1: -# use utf8; -# binmode( STDOUT, ":utf8" ); # c.f.: http://acis.openlib.org/dev/perl-unicode-struggle.html - - -# -# Global default settings: -# -my $g_empty_element_suffix = " />"; # Change to ">" for HTML output -my $g_tab_width = 4; - - -# -# Globals: -# - -# Regex to match balanced [brackets]. See Friedl's -# "Mastering Regular Expressions", 2nd Ed., pp. 328-331. -my $g_nested_brackets; -$g_nested_brackets = qr{ - (?> # Atomic matching - [^\[\]]+ # Anything other than brackets - | - \[ - (??{ $g_nested_brackets }) # Recursive set of nested brackets - \] - )* -}x; - - -# Table of hash values for escaped characters: -my %g_escape_table; -foreach my $char (split //, '\\`*_{}[]()>#+-.!') { - $g_escape_table{$char} = md5_hex($char); -} - - -# Global hashes, used by various utility routines -my %g_urls; -my %g_titles; -my %g_html_blocks; - -# Used to track when we're inside an ordered or unordered list -# (see _ProcessListItems() for details): -my $g_list_level = 0; - - -#### Blosxom plug-in interface ########################################## - -# Set $g_blosxom_use_meta to 1 to use Blosxom's meta plug-in to determine -# which posts Markdown should process, using a "meta-markup: markdown" -# header. If it's set to 0 (the default), Markdown will process all -# entries. -my $g_blosxom_use_meta = 0; - -sub start { 1; } -sub story { - my($pkg, $path, $filename, $story_ref, $title_ref, $body_ref) = @_; - - if ( (! $g_blosxom_use_meta) or - (defined($meta::markup) and ($meta::markup =~ /^\s*markdown\s*$/i)) - ){ - $$body_ref = Markdown($$body_ref); - } - 1; -} - - -#### Movable Type plug-in interface ##################################### -eval {require MT}; # Test to see if we're running in MT. -unless ($@) { - require MT; - import MT; - require MT::Template::Context; - import MT::Template::Context; - - eval {require MT::Plugin}; # Test to see if we're running >= MT 3.0. - unless ($@) { - require MT::Plugin; - import MT::Plugin; - my $plugin = new MT::Plugin({ - name => "Markdown", - description => "A plain-text-to-HTML formatting plugin. (Version: $VERSION)", - doc_link => 'http://daringfireball.net/projects/markdown/' - }); - MT->add_plugin( $plugin ); - } - - MT::Template::Context->add_container_tag(MarkdownOptions => sub { - my $ctx = shift; - my $args = shift; - my $builder = $ctx->stash('builder'); - my $tokens = $ctx->stash('tokens'); - - if (defined ($args->{'output'}) ) { - $ctx->stash('markdown_output', lc $args->{'output'}); - } - - defined (my $str = $builder->build($ctx, $tokens) ) - or return $ctx->error($builder->errstr); - $str; # return value - }); - - MT->add_text_filter('markdown' => { - label => 'Markdown', - docs => 'http://daringfireball.net/projects/markdown/', - on_format => sub { - my $text = shift; - my $ctx = shift; - my $raw = 0; - if (defined $ctx) { - my $output = $ctx->stash('markdown_output'); - if (defined $output && $output =~ m/^html/i) { - $g_empty_element_suffix = ">"; - $ctx->stash('markdown_output', ''); - } - elsif (defined $output && $output eq 'raw') { - $raw = 1; - $ctx->stash('markdown_output', ''); - } - else { - $raw = 0; - $g_empty_element_suffix = " />"; - } - } - $text = $raw ? $text : Markdown($text); - $text; - }, - }); - - # If SmartyPants is loaded, add a combo Markdown/SmartyPants text filter: - my $smartypants; - - { - no warnings "once"; - $smartypants = $MT::Template::Context::Global_filters{'smarty_pants'}; - } - - if ($smartypants) { - MT->add_text_filter('markdown_with_smartypants' => { - label => 'Markdown With SmartyPants', - docs => 'http://daringfireball.net/projects/markdown/', - on_format => sub { - my $text = shift; - my $ctx = shift; - if (defined $ctx) { - my $output = $ctx->stash('markdown_output'); - if (defined $output && $output eq 'html') { - $g_empty_element_suffix = ">"; - } - else { - $g_empty_element_suffix = " />"; - } - } - $text = Markdown($text); - $text = $smartypants->($text, '1'); - }, - }); - } -} -else { -#### BBEdit/command-line text filter interface ########################## -# Needs to be hidden from MT (and Blosxom when running in static mode). - - # We're only using $blosxom::version once; tell Perl not to warn us: - no warnings 'once'; - unless ( defined($blosxom::version) ) { - use warnings; - - #### Check for command-line switches: ################# - my %cli_opts; - use Getopt::Long; - Getopt::Long::Configure('pass_through'); - GetOptions(\%cli_opts, - 'version', - 'shortversion', - 'html4tags', - ); - if ($cli_opts{'version'}) { # Version info - print "\nThis is Markdown, version $VERSION.\n"; - print "Copyright 2004 John Gruber\n"; - print "http://daringfireball.net/projects/markdown/\n\n"; - exit 0; - } - if ($cli_opts{'shortversion'}) { # Just the version number string. - print $VERSION; - exit 0; - } - if ($cli_opts{'html4tags'}) { # Use HTML tag style instead of XHTML - $g_empty_element_suffix = ">"; - } - - - #### Process incoming text: ########################### - my $text; - { - local $/; # Slurp the whole file - $text = <>; - } - print Markdown($text); - } -} - - - -sub Markdown { -# -# Main function. The order in which other subs are called here is -# essential. Link and image substitutions need to happen before -# _EscapeSpecialChars(), so that any *'s or _'s in the <a> -# and <img> tags get encoded. -# - my $text = shift; - - # Clear the global hashes. If we don't clear these, you get conflicts - # from other articles when generating a page which contains more than - # one article (e.g. an index page that shows the N most recent - # articles): - %g_urls = (); - %g_titles = (); - %g_html_blocks = (); - - - # Standardize line endings: - $text =~ s{\r\n}{\n}g; # DOS to Unix - $text =~ s{\r}{\n}g; # Mac to Unix - - # Make sure $text ends with a couple of newlines: - $text .= "\n\n"; - - # Convert all tabs to spaces. - $text = _Detab($text); - - # Strip any lines consisting only of spaces and tabs. - # This makes subsequent regexen easier to write, because we can - # match consecutive blank lines with /\n+/ instead of something - # contorted like /[ \t]*\n+/ . - $text =~ s/^[ \t]+$//mg; - - # Turn block-level HTML blocks into hash entries - $text = _HashHTMLBlocks($text); - - # Strip link definitions, store in hashes. - $text = _StripLinkDefinitions($text); - - $text = _RunBlockGamut($text); - - $text = _UnescapeSpecialChars($text); - - return $text . "\n"; -} - - -sub _StripLinkDefinitions { -# -# Strips link definitions from text, stores the URLs and titles in -# hash references. -# - my $text = shift; - my $less_than_tab = $g_tab_width - 1; - - # Link defs are in the form: ^[id]: url "optional title" - while ($text =~ s{ - ^[ ]{0,$less_than_tab}\[(.+)\]: # id = $1 - [ \t]* - \n? # maybe *one* newline - [ \t]* - <?(\S+?)>? # url = $2 - [ \t]* - \n? # maybe one newline - [ \t]* - (?: - (?<=\s) # lookbehind for whitespace - ["(] - (.+?) # title = $3 - [")] - [ \t]* - )? # title is optional - (?:\n+|\Z) - } - {}mx) { - $g_urls{lc $1} = _EncodeAmpsAndAngles( $2 ); # Link IDs are case-insensitive - if ($3) { - $g_titles{lc $1} = $3; - $g_titles{lc $1} =~ s/"/&quot;/g; - } - } - - return $text; -} - - -sub _HashHTMLBlocks { - my $text = shift; - my $less_than_tab = $g_tab_width - 1; - - # Hashify HTML blocks: - # We only want to do this for block-level HTML tags, such as headers, - # lists, and tables. That's because we still want to wrap <p>s around - # "paragraphs" that are wrapped in non-block-level tags, such as anchors, - # phrase emphasis, and spans. The list of tags we're looking for is - # hard-coded: - my $block_tags_a = qr/p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del/; - my $block_tags_b = qr/p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math/; - - # First, look for nested blocks, e.g.: - # <div> - # <div> - # tags for inner block must be indented. - # </div> - # </div> - # - # The outermost tags must start at the left margin for this to match, and - # the inner nested divs must be indented. - # We need to do this before the next, more liberal match, because the next - # match will start at the first `<div>` and stop at the first `</div>`. - $text =~ s{ - ( # save in $1 - ^ # start of line (with /m) - <($block_tags_a) # start tag = $2 - \b # word break - (.*\n)*? # any number of lines, minimally matching - </\2> # the matching end tag - [ \t]* # trailing spaces/tabs - (?=\n+|\Z) # followed by a newline or end of document - ) - }{ - my $key = md5_hex($1); - $g_html_blocks{$key} = $1; - "\n\n" . $key . "\n\n"; - }egmx; - - - # - # Now match more liberally, simply from `\n<tag>` to `</tag>\n` - # - $text =~ s{ - ( # save in $1 - ^ # start of line (with /m) - <($block_tags_b) # start tag = $2 - \b # word break - (.*\n)*? # any number of lines, minimally matching - .*</\2> # the matching end tag - [ \t]* # trailing spaces/tabs - (?=\n+|\Z) # followed by a newline or end of document - ) - }{ - my $key = md5_hex($1); - $g_html_blocks{$key} = $1; - "\n\n" . $key . "\n\n"; - }egmx; - # Special case just for <hr />. It was easier to make a special case than - # to make the other regex more complicated. - $text =~ s{ - (?: - (?<=\n\n) # Starting after a blank line - | # or - \A\n? # the beginning of the doc - ) - ( # save in $1 - [ ]{0,$less_than_tab} - <(hr) # start tag = $2 - \b # word break - ([^<>])*? # - /?> # the matching end tag - [ \t]* - (?=\n{2,}|\Z) # followed by a blank line or end of document - ) - }{ - my $key = md5_hex($1); - $g_html_blocks{$key} = $1; - "\n\n" . $key . "\n\n"; - }egx; - - # Special case for standalone HTML comments: - $text =~ s{ - (?: - (?<=\n\n) # Starting after a blank line - | # or - \A\n? # the beginning of the doc - ) - ( # save in $1 - [ ]{0,$less_than_tab} - (?s: - <! - (--.*?--\s*)+ - > - ) - [ \t]* - (?=\n{2,}|\Z) # followed by a blank line or end of document - ) - }{ - my $key = md5_hex($1); - $g_html_blocks{$key} = $1; - "\n\n" . $key . "\n\n"; - }egx; - - - return $text; -} - - -sub _RunBlockGamut { -# -# These are all the transformations that form block-level -# tags like paragraphs, headers, and list items. -# - my $text = shift; - - $text = _DoHeaders($text); - - # Do Horizontal Rules: - $text =~ s{^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$}{\n<hr$g_empty_element_suffix\n}gmx; - $text =~ s{^[ ]{0,2}([ ]? -[ ]?){3,}[ \t]*$}{\n<hr$g_empty_element_suffix\n}gmx; - $text =~ s{^[ ]{0,2}([ ]? _[ ]?){3,}[ \t]*$}{\n<hr$g_empty_element_suffix\n}gmx; - - $text = _DoLists($text); - - $text = _DoCodeBlocks($text); - - $text = _DoBlockQuotes($text); - - # We already ran _HashHTMLBlocks() before, in Markdown(), but that - # was to escape raw HTML in the original Markdown source. This time, - # we're escaping the markup we've just created, so that we don't wrap - # <p> tags around block-level tags. - $text = _HashHTMLBlocks($text); - - $text = _FormParagraphs($text); - - return $text; -} - - -sub _RunSpanGamut { -# -# These are all the transformations that occur *within* block-level -# tags like paragraphs, headers, and list items. -# - my $text = shift; - - $text = _DoCodeSpans($text); - - $text = _EscapeSpecialChars($text); - - # Process anchor and image tags. Images must come first, - # because ![foo][f] looks like an anchor. - $text = _DoImages($text); - $text = _DoAnchors($text); - - # Make links out of things like `<http://example.com/>` - # Must come after _DoAnchors(), because you can use < and > - # delimiters in inline links like [this](<url>). - $text = _DoAutoLinks($text); - - $text = _EncodeAmpsAndAngles($text); - - $text = _DoItalicsAndBold($text); - - # Do hard breaks: - $text =~ s/ {2,}\n/ <br$g_empty_element_suffix\n/g; - - return $text; -} - - -sub _EscapeSpecialChars { - my $text = shift; - my $tokens ||= _TokenizeHTML($text); - - $text = ''; # rebuild $text from the tokens -# my $in_pre = 0; # Keep track of when we're inside <pre> or <code> tags. -# my $tags_to_skip = qr!<(/?)(?:pre|code|kbd|script|math)[\s>]!; - - foreach my $cur_token (@$tokens) { - if ($cur_token->[0] eq "tag") { - # Within tags, encode * and _ so they don't conflict - # with their use in Markdown for italics and strong. - # We're replacing each such character with its - # corresponding MD5 checksum value; this is likely - # overkill, but it should prevent us from colliding - # with the escape values by accident. - $cur_token->[1] =~ s! \* !$g_escape_table{'*'}!gx; - $cur_token->[1] =~ s! _ !$g_escape_table{'_'}!gx; - $text .= $cur_token->[1]; - } else { - my $t = $cur_token->[1]; - $t = _EncodeBackslashEscapes($t); - $text .= $t; - } - } - return $text; -} - - -sub _DoAnchors { -# -# Turn Markdown link shortcuts into XHTML <a> tags. -# - my $text = shift; - - # - # First, handle reference-style links: [link text] [id] - # - $text =~ s{ - ( # wrap whole match in $1 - \[ - ($g_nested_brackets) # link text = $2 - \] - - [ ]? # one optional space - (?:\n[ ]*)? # one optional newline followed by spaces - - \[ - (.*?) # id = $3 - \] - ) - }{ - my $result; - my $whole_match = $1; - my $link_text = $2; - my $link_id = lc $3; - - if ($link_id eq "") { - $link_id = lc $link_text; # for shortcut links like [this][]. - } - - if (defined $g_urls{$link_id}) { - my $url = $g_urls{$link_id}; - $url =~ s! \* !$g_escape_table{'*'}!gx; # We've got to encode these to avoid - $url =~ s! _ !$g_escape_table{'_'}!gx; # conflicting with italics/bold. - $result = "<a href=\"$url\""; - if ( defined $g_titles{$link_id} ) { - my $title = $g_titles{$link_id}; - $title =~ s! \* !$g_escape_table{'*'}!gx; - $title =~ s! _ !$g_escape_table{'_'}!gx; - $result .= " title=\"$title\""; - } - $result .= ">$link_text</a>"; - } - else { - $result = $whole_match; - } - $result; - }xsge; - - # - # Next, inline-style links: [link text](url "optional title") - # - $text =~ s{ - ( # wrap whole match in $1 - \[ - ($g_nested_brackets) # link text = $2 - \] - \( # literal paren - [ \t]* - <?(.*?)>? # href = $3 - [ \t]* - ( # $4 - (['"]) # quote char = $5 - (.*?) # Title = $6 - \5 # matching quote - )? # title is optional - \) - ) - }{ - my $result; - my $whole_match = $1; - my $link_text = $2; - my $url = $3; - my $title = $6; - - $url =~ s! \* !$g_escape_table{'*'}!gx; # We've got to encode these to avoid - $url =~ s! _ !$g_escape_table{'_'}!gx; # conflicting with italics/bold. - $result = "<a href=\"$url\""; - - if (defined $title) { - $title =~ s/"/&quot;/g; - $title =~ s! \* !$g_escape_table{'*'}!gx; - $title =~ s! _ !$g_escape_table{'_'}!gx; - $result .= " title=\"$title\""; - } - - $result .= ">$link_text</a>"; - - $result; - }xsge; - - return $text; -} - - -sub _DoImages { -# -# Turn Markdown image shortcuts into <img> tags. -# - my $text = shift; - - # - # First, handle reference-style labeled images: ![alt text][id] - # - $text =~ s{ - ( # wrap whole match in $1 - !\[ - (.*?) # alt text = $2 - \] - - [ ]? # one optional space - (?:\n[ ]*)? # one optional newline followed by spaces - - \[ - (.*?) # id = $3 - \] - - ) - }{ - my $result; - my $whole_match = $1; - my $alt_text = $2; - my $link_id = lc $3; - - if ($link_id eq "") { - $link_id = lc $alt_text; # for shortcut links like ![this][]. - } - - $alt_text =~ s/"/&quot;/g; - if (defined $g_urls{$link_id}) { - my $url = $g_urls{$link_id}; - $url =~ s! \* !$g_escape_table{'*'}!gx; # We've got to encode these to avoid - $url =~ s! _ !$g_escape_table{'_'}!gx; # conflicting with italics/bold. - $result = "<img src=\"$url\" alt=\"$alt_text\""; - if (defined $g_titles{$link_id}) { - my $title = $g_titles{$link_id}; - $title =~ s! \* !$g_escape_table{'*'}!gx; - $title =~ s! _ !$g_escape_table{'_'}!gx; - $result .= " title=\"$title\""; - } - $result .= $g_empty_element_suffix; - } - else { - # If there's no such link ID, leave intact: - $result = $whole_match; - } - - $result; - }xsge; - - # - # Next, handle inline images: ![alt text](url "optional title") - # Don't forget: encode * and _ - - $text =~ s{ - ( # wrap whole match in $1 - !\[ - (.*?) # alt text = $2 - \] - \( # literal paren - [ \t]* - <?(\S+?)>? # src url = $3 - [ \t]* - ( # $4 - (['"]) # quote char = $5 - (.*?) # title = $6 - \5 # matching quote - [ \t]* - )? # title is optional - \) - ) - }{ - my $result; - my $whole_match = $1; - my $alt_text = $2; - my $url = $3; - my $title = ''; - if (defined($6)) { - $title = $6; - } - - $alt_text =~ s/"/&quot;/g; - $title =~ s/"/&quot;/g; - $url =~ s! \* !$g_escape_table{'*'}!gx; # We've got to encode these to avoid - $url =~ s! _ !$g_escape_table{'_'}!gx; # conflicting with italics/bold. - $result = "<img src=\"$url\" alt=\"$alt_text\""; - if (defined $title) { - $title =~ s! \* !$g_escape_table{'*'}!gx; - $title =~ s! _ !$g_escape_table{'_'}!gx; - $result .= " title=\"$title\""; - } - $result .= $g_empty_element_suffix; - - $result; - }xsge; - - return $text; -} - - -sub _DoHeaders { - my $text = shift; - - # Setext-style headers: - # Header 1 - # ======== - # - # Header 2 - # -------- - # - $text =~ s{ ^(.+)[ \t]*\n=+[ \t]*\n+ }{ - "<h1>" . _RunSpanGamut($1) . "</h1>\n\n"; - }egmx; - - $text =~ s{ ^(.+)[ \t]*\n-+[ \t]*\n+ }{ - "<h2>" . _RunSpanGamut($1) . "</h2>\n\n"; - }egmx; - - - # atx-style headers: - # # Header 1 - # ## Header 2 - # ## Header 2 with closing hashes ## - # ... - # ###### Header 6 - # - $text =~ s{ - ^(\#{1,6}) # $1 = string of #'s - [ \t]* - (.+?) # $2 = Header text - [ \t]* - \#* # optional closing #'s (not counted) - \n+ - }{ - my $h_level = length($1); - "<h$h_level>" . _RunSpanGamut($2) . "</h$h_level>\n\n"; - }egmx; - - return $text; -} - - -sub _DoLists { -# -# Form HTML ordered (numbered) and unordered (bulleted) lists. -# - my $text = shift; - my $less_than_tab = $g_tab_width - 1; - - # Re-usable patterns to match list item bullets and number markers: - my $marker_ul = qr/[*+-]/; - my $marker_ol = qr/\d+[.]/; - my $marker_any = qr/(?:$marker_ul|$marker_ol)/; - - # Re-usable pattern to match any entirel ul or ol list: - my $whole_list = qr{ - ( # $1 = whole list - ( # $2 - [ ]{0,$less_than_tab} - (${marker_any}) # $3 = first list item marker - [ \t]+ - ) - (?s:.+?) - ( # $4 - \z - | - \n{2,} - (?=\S) - (?! # Negative lookahead for another list item marker - [ \t]* - ${marker_any}[ \t]+ - ) - ) - ) - }mx; - - # We use a different prefix before nested lists than top-level lists. - # See extended comment in _ProcessListItems(). - # - # Note: There's a bit of duplication here. My original implementation - # created a scalar regex pattern as the conditional result of the test on - # $g_list_level, and then only ran the $text =~ s{...}{...}egmx - # substitution once, using the scalar as the pattern. This worked, - # everywhere except when running under MT on my hosting account at Pair - # Networks. There, this caused all rebuilds to be killed by the reaper (or - # perhaps they crashed, but that seems incredibly unlikely given that the - # same script on the same server ran fine *except* under MT. I've spent - # more time trying to figure out why this is happening than I'd like to - # admit. My only guess, backed up by the fact that this workaround works, - # is that Perl optimizes the substition when it can figure out that the - # pattern will never change, and when this optimization isn't on, we run - # afoul of the reaper. Thus, the slightly redundant code to that uses two - # static s/// patterns rather than one conditional pattern. - - if ($g_list_level) { - $text =~ s{ - ^ - $whole_list - }{ - my $list = $1; - my $list_type = ($3 =~ m/$marker_ul/) ? "ul" : "ol"; - # Turn double returns into triple returns, so that we can make a - # paragraph for the last item in a list, if necessary: - $list =~ s/\n{2,}/\n\n\n/g; - my $result = _ProcessListItems($list, $marker_any); - $result = "<$list_type>\n" . $result . "</$list_type>\n"; - $result; - }egmx; - } - else { - $text =~ s{ - (?:(?<=\n\n)|\A\n?) - $whole_list - }{ - my $list = $1; - my $list_type = ($3 =~ m/$marker_ul/) ? "ul" : "ol"; - # Turn double returns into triple returns, so that we can make a - # paragraph for the last item in a list, if necessary: - $list =~ s/\n{2,}/\n\n\n/g; - my $result = _ProcessListItems($list, $marker_any); - $result = "<$list_type>\n" . $result . "</$list_type>\n"; - $result; - }egmx; - } - - - return $text; -} - - -sub _ProcessListItems { -# -# Process the contents of a single ordered or unordered list, splitting it -# into individual list items. -# - - my $list_str = shift; - my $marker_any = shift; - - - # The $g_list_level global keeps track of when we're inside a list. - # Each time we enter a list, we increment it; when we leave a list, - # we decrement. If it's zero, we're not in a list anymore. - # - # We do this because when we're not inside a list, we want to treat - # something like this: - # - # I recommend upgrading to version - # 8. Oops, now this line is treated - # as a sub-list. - # - # As a single paragraph, despite the fact that the second line starts - # with a digit-period-space sequence. - # - # Whereas when we're inside a list (or sub-list), that line will be - # treated as the start of a sub-list. What a kludge, huh? This is - # an aspect of Markdown's syntax that's hard to parse perfectly - # without resorting to mind-reading. Perhaps the solution is to - # change the syntax rules such that sub-lists must start with a - # starting cardinal number; e.g. "1." or "a.". - - $g_list_level++; - - # trim trailing blank lines: - $list_str =~ s/\n{2,}\z/\n/; - - - $list_str =~ s{ - (\n)? # leading line = $1 - (^[ \t]*) # leading whitespace = $2 - ($marker_any) [ \t]+ # list marker = $3 - ((?s:.+?) # list item text = $4 - (\n{1,2})) - (?= \n* (\z | \2 ($marker_any) [ \t]+)) - }{ - my $item = $4; - my $leading_line = $1; - my $leading_space = $2; - - if ($leading_line or ($item =~ m/\n{2,}/)) { - $item = _RunBlockGamut(_Outdent($item)); - } - else { - # Recursion for sub-lists: - $item = _DoLists(_Outdent($item)); - chomp $item; - $item = _RunSpanGamut($item); - } - - "<li>" . $item . "</li>\n"; - }egmx; - - $g_list_level--; - return $list_str; -} - - - -sub _DoCodeBlocks { -# -# Process Markdown `<pre><code>` blocks. -# - - my $text = shift; - - $text =~ s{ - (?:\n\n|\A) - ( # $1 = the code block -- one or more lines, starting with a space/tab - (?: - (?:[ ]{$g_tab_width} | \t) # Lines must start with a tab or a tab-width of spaces - .*\n+ - )+ - ) - ((?=^[ ]{0,$g_tab_width}\S)|\Z) # Lookahead for non-space at line-start, or end of doc - }{ - my $codeblock = $1; - my $result; # return value - - $codeblock = _EncodeCode(_Outdent($codeblock)); - $codeblock = _Detab($codeblock); - $codeblock =~ s/\A\n+//; # trim leading newlines - $codeblock =~ s/\s+\z//; # trim trailing whitespace - - $result = "\n\n<pre><code>" . $codeblock . "\n</code></pre>\n\n"; - - $result; - }egmx; - - return $text; -} - - -sub _DoCodeSpans { -# -# * Backtick quotes are used for <code></code> spans. -# -# * You can use multiple backticks as the delimiters if you want to -# include literal backticks in the code span. So, this input: -# -# Just type ``foo `bar` baz`` at the prompt. -# -# Will translate to: -# -# <p>Just type <code>foo `bar` baz</code> at the prompt.</p> -# -# There's no arbitrary limit to the number of backticks you -# can use as delimters. If you need three consecutive backticks -# in your code, use four for delimiters, etc. -# -# * You can use spaces to get literal backticks at the edges: -# -# ... type `` `bar` `` ... -# -# Turns to: -# -# ... type <code>`bar`</code> ... -# - - my $text = shift; - - $text =~ s@ - (`+) # $1 = Opening run of ` - (.+?) # $2 = The code block - (?<!`) - \1 # Matching closer - (?!`) - @ - my $c = "$2"; - $c =~ s/^[ \t]*//g; # leading whitespace - $c =~ s/[ \t]*$//g; # trailing whitespace - $c = _EncodeCode($c); - "<code>$c</code>"; - @egsx; - - return $text; -} - - -sub _EncodeCode { -# -# Encode/escape certain characters inside Markdown code runs. -# The point is that in code, these characters are literals, -# and lose their special Markdown meanings. -# - local $_ = shift; - - # Encode all ampersands; HTML entities are not - # entities within a Markdown code span. - s/&/&amp;/g; - - # Encode $'s, but only if we're running under Blosxom. - # (Blosxom interpolates Perl variables in article bodies.) - { - no warnings 'once'; - if (defined($blosxom::version)) { - s/\$/&#036;/g; - } - } - - - # Do the angle bracket song and dance: - s! < !&lt;!gx; - s! > !&gt;!gx; - - # Now, escape characters that are magic in Markdown: - s! \* !$g_escape_table{'*'}!gx; - s! _ !$g_escape_table{'_'}!gx; - s! { !$g_escape_table{'{'}!gx; - s! } !$g_escape_table{'}'}!gx; - s! \[ !$g_escape_table{'['}!gx; - s! \] !$g_escape_table{']'}!gx; - s! \\ !$g_escape_table{'\\'}!gx; - - return $_; -} - - -sub _DoItalicsAndBold { - my $text = shift; - - # <strong> must go first: - $text =~ s{ (\*\*|__) (?=\S) (.+?[*_]*) (?<=\S) \1 } - {<strong>$2</strong>}gsx; - - $text =~ s{ (\*|_) (?=\S) (.+?) (?<=\S) \1 } - {<em>$2</em>}gsx; - - return $text; -} - - -sub _DoBlockQuotes { - my $text = shift; - - $text =~ s{ - ( # Wrap whole match in $1 - ( - ^[ \t]*>[ \t]? # '>' at the start of a line - .+\n # rest of the first line - (.+\n)* # subsequent consecutive lines - \n* # blanks - )+ - ) - }{ - my $bq = $1; - $bq =~ s/^[ \t]*>[ \t]?//gm; # trim one level of quoting - $bq =~ s/^[ \t]+$//mg; # trim whitespace-only lines - $bq = _RunBlockGamut($bq); # recurse - - $bq =~ s/^/ /g; - # These leading spaces screw with <pre> content, so we need to fix that: - $bq =~ s{ - (\s*<pre>.+?</pre>) - }{ - my $pre = $1; - $pre =~ s/^ //mg; - $pre; - }egsx; - - "<blockquote>\n$bq\n</blockquote>\n\n"; - }egmx; - - - return $text; -} - - -sub _FormParagraphs { -# -# Params: -# $text - string to process with html <p> tags -# - my $text = shift; - - # Strip leading and trailing lines: - $text =~ s/\A\n+//; - $text =~ s/\n+\z//; - - my @grafs = split(/\n{2,}/, $text); - - # - # Wrap <p> tags. - # - foreach (@grafs) { - unless (defined( $g_html_blocks{$_} )) { - $_ = _RunSpanGamut($_); - s/^([ \t]*)/<p>/; - $_ .= "</p>"; - } - } - - # - # Unhashify HTML blocks - # - foreach (@grafs) { - if (defined( $g_html_blocks{$_} )) { - $_ = $g_html_blocks{$_}; - } - } - - return join "\n\n", @grafs; -} - - -sub _EncodeAmpsAndAngles { -# Smart processing for ampersands and angle brackets that need to be encoded. - - my $text = shift; - - # Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin: - # http://bumppo.net/projects/amputator/ - $text =~ s/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/&amp;/g; - - # Encode naked <'s - $text =~ s{<(?![a-z/?\$!])}{&lt;}gi; - - return $text; -} - - -sub _EncodeBackslashEscapes { -# -# Parameter: String. -# Returns: The string, with after processing the following backslash -# escape sequences. -# - local $_ = shift; - - s! \\\\ !$g_escape_table{'\\'}!gx; # Must process escaped backslashes first. - s! \\` !$g_escape_table{'`'}!gx; - s! \\\* !$g_escape_table{'*'}!gx; - s! \\_ !$g_escape_table{'_'}!gx; - s! \\\{ !$g_escape_table{'{'}!gx; - s! \\\} !$g_escape_table{'}'}!gx; - s! \\\[ !$g_escape_table{'['}!gx; - s! \\\] !$g_escape_table{']'}!gx; - s! \\\( !$g_escape_table{'('}!gx; - s! \\\) !$g_escape_table{')'}!gx; - s! \\> !$g_escape_table{'>'}!gx; - s! \\\# !$g_escape_table{'#'}!gx; - s! \\\+ !$g_escape_table{'+'}!gx; - s! \\\- !$g_escape_table{'-'}!gx; - s! \\\. !$g_escape_table{'.'}!gx; - s{ \\! }{$g_escape_table{'!'}}gx; - - return $_; -} - - -sub _DoAutoLinks { - my $text = shift; - - $text =~ s{<((https?|ftp):[^'">\s]+)>}{<a href="$1">$1</a>}gi; - - # Email addresses: <address@domain.foo> - $text =~ s{ - < - (?:mailto:)? - ( - [-.\w]+ - \@ - [-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+ - ) - > - }{ - _EncodeEmailAddress( _UnescapeSpecialChars($1) ); - }egix; - - return $text; -} - - -sub _EncodeEmailAddress { -# -# Input: an email address, e.g. "foo@example.com" -# -# Output: the email address as a mailto link, with each character -# of the address encoded as either a decimal or hex entity, in -# the hopes of foiling most address harvesting spam bots. E.g.: -# -# <a href="&#x6D;&#97;&#105;&#108;&#x74;&#111;:&#102;&#111;&#111;&#64;&#101; -# x&#x61;&#109;&#x70;&#108;&#x65;&#x2E;&#99;&#111;&#109;">&#102;&#111;&#111; -# &#64;&#101;x&#x61;&#109;&#x70;&#108;&#x65;&#x2E;&#99;&#111;&#109;</a> -# -# Based on a filter by Matthew Wickline, posted to the BBEdit-Talk -# mailing list: <http://tinyurl.com/yu7ue> -# - - my $addr = shift; - - srand; - my @encode = ( - sub { '&#' . ord(shift) . ';' }, - sub { '&#x' . sprintf( "%X", ord(shift) ) . ';' }, - sub { shift }, - ); - - $addr = "mailto:" . $addr; - - $addr =~ s{(.)}{ - my $char = $1; - if ( $char eq '@' ) { - # this *must* be encoded. I insist. - $char = $encode[int rand 1]->($char); - } elsif ( $char ne ':' ) { - # leave ':' alone (to spot mailto: later) - my $r = rand; - # roughly 10% raw, 45% hex, 45% dec - $char = ( - $r > .9 ? $encode[2]->($char) : - $r < .45 ? $encode[1]->($char) : - $encode[0]->($char) - ); - } - $char; - }gex; - - $addr = qq{<a href="$addr">$addr</a>}; - $addr =~ s{">.+?:}{">}; # strip the mailto: from the visible part - - return $addr; -} - - -sub _UnescapeSpecialChars { -# -# Swap back in all the special characters we've hidden. -# - my $text = shift; - - while( my($char, $hash) = each(%g_escape_table) ) { - $text =~ s/$hash/$char/g; - } - return $text; -} - - -sub _TokenizeHTML { -# -# Parameter: String containing HTML markup. -# Returns: Reference to an array of the tokens comprising the input -# string. Each token is either a tag (possibly with nested, -# tags contained therein, such as <a href="<MTFoo>">, or a -# run of text between tags. Each element of the array is a -# two-element array; the first is either 'tag' or 'text'; -# the second is the actual value. -# -# -# Derived from the _tokenize() subroutine from Brad Choate's MTRegex plugin. -# <http://www.bradchoate.com/past/mtregex.php> -# - - my $str = shift; - my $pos = 0; - my $len = length $str; - my @tokens; - - my $depth = 6; - my $nested_tags = join('|', ('(?:<[a-z/!$](?:[^<>]') x $depth) . (')*>)' x $depth); - my $match = qr/(?s: <! ( -- .*? -- \s* )+ > ) | # comment - (?s: <\? .*? \?> ) | # processing instruction - $nested_tags/ix; # nested tags - - while ($str =~ m/($match)/g) { - my $whole_tag = $1; - my $sec_start = pos $str; - my $tag_start = $sec_start - length $whole_tag; - if ($pos < $tag_start) { - push @tokens, ['text', substr($str, $pos, $tag_start - $pos)]; - } - push @tokens, ['tag', $whole_tag]; - $pos = pos $str; - } - push @tokens, ['text', substr($str, $pos, $len - $pos)] if $pos < $len; - \@tokens; -} - - -sub _Outdent { -# -# Remove one level of line-leading tabs or spaces -# - my $text = shift; - - $text =~ s/^(\t|[ ]{1,$g_tab_width})//gm; - return $text; -} - - -sub _Detab { -# -# Cribbed from a post by Bart Lateur: -# <http://www.nntp.perl.org/group/perl.macperl.anyperl/154> -# - my $text = shift; - - $text =~ s{(.*?)\t}{$1.(' ' x ($g_tab_width - length($1) % $g_tab_width))}ge; - return $text; -} - - -1; - -__END__ - - -=pod - -=head1 NAME - -B<Markdown> - - -=head1 SYNOPSIS - -B<Markdown.pl> [ B<--html4tags> ] [ B<--version> ] [ B<-shortversion> ] - [ I<file> ... ] - - -=head1 DESCRIPTION - -Markdown is a text-to-HTML filter; it translates an easy-to-read / -easy-to-write structured text format into HTML. Markdown's text format -is most similar to that of plain text email, and supports features such -as headers, *emphasis*, code blocks, blockquotes, and links. - -Markdown's syntax is designed not as a generic markup language, but -specifically to serve as a front-end to (X)HTML. You can use span-level -HTML tags anywhere in a Markdown document, and you can use block level -HTML tags (like <div> and <table> as well). - -For more information about Markdown's syntax, see: - - http://daringfireball.net/projects/markdown/ - - -=head1 OPTIONS - -Use "--" to end switch parsing. For example, to open a file named "-z", use: - - Markdown.pl -- -z - -=over 4 - - -=item B<--html4tags> - -Use HTML 4 style for empty element tags, e.g.: - - <br> - -instead of Markdown's default XHTML style tags, e.g.: - - <br /> - - -=item B<-v>, B<--version> - -Display Markdown's version number and copyright information. - - -=item B<-s>, B<--shortversion> - -Display the short-form version number. - - -=back - - - -=head1 BUGS - -To file bug reports or feature requests (other than topics listed in the -Caveats section above) please send email to: - - support@daringfireball.net - -Please include with your report: (1) the example input; (2) the output -you expected; (3) the output Markdown actually produced. - - -=head1 VERSION HISTORY - -See the readme file for detailed release notes for this version. - -1.0.1 - 14 Dec 2004 - -1.0 - 28 Aug 2004 - - -=head1 AUTHOR - - John Gruber - http://daringfireball.net - - PHP port and other contributions by Michel Fortin - http://michelf.com - - -=head1 COPYRIGHT AND LICENSE - -Copyright (c) 2003-2004 John Gruber -<http://daringfireball.net/> -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -* Neither the name "Markdown" nor the names of its contributors may - be used to endorse or promote products derived from this software - without specific prior written permission. - -This software is provided by the copyright holders and contributors "as -is" and any express or implied warranties, including, but not limited -to, the implied warranties of merchantability and fitness for a -particular purpose are disclaimed. In no event shall the copyright owner -or contributors be liable for any direct, indirect, incidental, special, -exemplary, or consequential damages (including, but not limited to, -procurement of substitute goods or services; loss of use, data, or -profits; or business interruption) however caused and on any theory of -liability, whether in contract, strict liability, or tort (including -negligence or otherwise) arising in any way out of the use of this -software, even if advised of the possibility of such damage. - -=cut diff --git a/bin/contrib/md2html.awk b/bin/contrib/md2html.awk @@ -1,427 +0,0 @@ -#!/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("&", "\\&amp;", t); - gsub("<", "\\&lt;", 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 = "&#8212;"; - return t1 tag nextil(t2); - } - # Inline Code - if(tag == "`"){ - if(sub(/^`/, "", t2)){ - if(!match(t2, /``/)) - return t1 "&#8221;" nextil(t2); - ilcode2 = !ilcode2; - } - else if(ilcode2) - return t1 tag nextil(t2); - tag = "<code>"; - if(ilcode){ - t1 = eschtml(t1); - tag = "</code>"; - } - 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 "<a href=\"" url "\">" linktext "</a>" 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 "&lt;" 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 "&amp;" 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 "<img src=\"" url "\" alt=\"" alt "\"" title " />" 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 "<img src=\"" r "\" alt=\"" alt "\" />" 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 "<a href=\"" url "\"" title ">" nextil(linktext) "</a>" 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 "<a href=\"" r "\" />" nextil(linktext) "</a>" 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 "</" tag ">"); - 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("</pre></code>"); - for(; !text && block[nl] == "blockquote"; nl--) - oprint("</blockquote>"); - 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 ">)|((^<hr ?\\/?)|(--)>$)")) - html = 1; - if(html && match($0, /^<hr/)) - hr = 1; - oprint($0); - next; -} - -html && (/(^<\/(address|blockquote|center|dir|div|dl|fieldset|form|h[1-6r]|\ -isindex|menu|noframes|noscript|ol|p|pre|table|ul).*)|(--)>$/ || -(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("</pre></code>"); - 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("</li><li>"); -} -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("</pre></code>"); - 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("</li>"); - oprint("</" block[nl] ">"); - } -} -nnl > nl { - for(; nl < nnl; nl++){ - block[nl + 1] = nblock[nl + 1]; - oprint("<" block[nl + 1] ">"); - if(match(block[nl + 1], /[ou]l/)) - oprint("<li>"); - } -} -hr { - oprint("<hr>"); - next; -} - -# Code blocks -code && /^$/ { - if(blanK) - oprint(""); - blank = 1; - next; -} -!text && sub(/^( | )/, "") { - if(blanK) - oprint(""); - blank = 0; - if(!code) - oprint("<code><pre>"); - code = 1; - $0 = eschtml($0); - oprint($0); - next; -} -code { - oprint("</pre></code>"); - 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("</pre></code>"); - code = 0; - } - printp(par); - for(; nl > 0; nl--){ - if(match(block[nl], /[ou]l/)) - oprint("</li>"); - oprint("</" block[nl] ">"); - } - gsub(/<<[^\"]*/, "", otext); - print(otext); -} diff --git a/bin/contrib/urldecode.awk b/bin/contrib/urldecode.awk @@ -1,39 +0,0 @@ -#!/usr/bin/awk -f -BEGIN { - hextab ["0"] = 0; hextab ["8"] = 8; - hextab ["1"] = 1; hextab ["9"] = 9; - hextab ["2"] = 2; hextab ["A"] = hextab ["a"] = 10 - hextab ["3"] = 3; hextab ["B"] = hextab ["b"] = 11; - hextab ["4"] = 4; hextab ["C"] = hextab ["c"] = 12; - hextab ["5"] = 5; hextab ["D"] = hextab ["d"] = 13; - hextab ["6"] = 6; hextab ["E"] = hextab ["e"] = 14; - hextab ["7"] = 7; hextab ["F"] = hextab ["f"] = 15; -} -{ - decoded = "" - i = 1 - len = length ($0) - while ( i <= len ) { - c = substr ($0, i, 1) - if ( c == "%" ) { - if ( i+2 <= len ) { - c1 = substr ($0, i+1, 1) - c2 = substr ($0, i+2, 1) - if ( hextab [c1] == "" || hextab [c2] == "" ) { - print "WARNING: invalid hex encoding: %" c1 c2 | "cat >&2" - } else { - code = 0 + hextab [c1] * 16 + hextab [c2] + 0 - c = sprintf ("%c", code) - i = i + 2 - } - } else { - print "WARNING: invalid % encoding: " substr ($0, i, len - i) - } - } else if ( c == "+" ) { - c = " " - } - decoded = decoded c - ++i - } - print decoded -} diff --git a/bin/contrib/urlencode.awk b/bin/contrib/urlencode.awk @@ -1,126 +0,0 @@ -# Taken from http://www.shelldorado.com/scripts/cmds/urlencode -########################################################################## -# Title : urlencode - encode URL data -# Author : Heiner Steven (heiner.steven@odn.de) -# Date : 2000-03-15 -# Requires : awk -# Categories : File Conversion, WWW, CGI -# SCCS-Id. : @(#) urlencode 1.4 06/10/29 -########################################################################## -# Description -# Encode data according to -# RFC 1738: "Uniform Resource Locators (URL)" and -# RFC 1866: "Hypertext Markup Language - 2.0" (HTML) -# -# This encoding is used i.e. for the MIME type -# "application/x-www-form-urlencoded" -# -# Notes -# o The default behaviour is not to encode the line endings. This -# may not be what was intended, because the result will be -# multiple lines of output (which cannot be used in an URL or a -# HTTP "POST" request). If the desired output should be one -# line, use the "-l" option. -# -# o The "-l" option assumes, that the end-of-line is denoted by -# the character LF (ASCII 10). This is not true for Windows or -# Mac systems, where the end of a line is denoted by the two -# characters CR LF (ASCII 13 10). -# We use this for symmetry; data processed in the following way: -# cat | urlencode -l | urldecode -l -# should (and will) result in the original data -# -# o Large lines (or binary files) will break many AWK -# implementations. If you get the message -# awk: record `...' too long -# record number xxx -# consider using GNU AWK (gawk). -# -# o urlencode will always terminate it's output with an EOL -# character -# -# Thanks to Stefan Brozinski for pointing out a bug related to non-standard -# locales. -# -# See also -# urldecode -########################################################################## - -PN=`basename "$0"` # Program name -VER='1.4' - -: ${AWK=awk} - -Usage () { - echo >&2 "$PN - encode URL data, $VER -usage: $PN [-l] [file ...] - -l: encode line endings (result will be one line of output) - -The default is to encode each input line on its own." - exit 1 -} - -Msg () { - for MsgLine - do echo "$PN: $MsgLine" >&2 - done -} - -Fatal () { Msg "$@"; exit 1; } - -set -- `getopt hl "$@" 2>/dev/null` || Usage -[ $# -lt 1 ] && Usage # "getopt" detected an error - -EncodeEOL=no -while [ $# -gt 0 ] -do - case "$1" in - -l) EncodeEOL=yes;; - --) shift; break;; - -h) Usage;; - -*) Usage;; - *) break;; # First file name - esac - shift -done - -LANG=C export LANG -$AWK ' - BEGIN { - # We assume an awk implementation that is just plain dumb. - # We will convert an character to its ASCII value with the - # table ord[], and produce two-digit hexadecimal output - # without the printf("%02X") feature. - - EOL = "%0A" # "end of line" string (encoded) - split ("1 2 3 4 5 6 7 8 9 A B C D E F", hextab, " ") - hextab [0] = 0 - for ( i=1; i<=255; ++i ) ord [ sprintf ("%c", i) "" ] = i + 0 - if ("'"$EncodeEOL"'" == "yes") EncodeEOL = 1; else EncodeEOL = 0 - } - { - encoded = "" - for ( i=1; i<=length ($0); ++i ) { - c = substr ($0, i, 1) - if ( c ~ /[a-zA-Z0-9.-]/ ) { - encoded = encoded c # safe character - } else if ( c == " " ) { - encoded = encoded "+" # special handling - } else { - # unsafe character, encode it as a two-digit hex-number - lo = ord [c] % 16 - hi = int (ord [c] / 16); - encoded = encoded "%" hextab [hi] hextab [lo] - } - } - if ( EncodeEOL ) { - printf ("%s", encoded EOL) - } else { - print encoded - } - } - END { - #if ( EncodeEOL ) print "" - } -' "$@" - diff --git a/bin/contrib/webserver.rc b/bin/contrib/webserver.rc @@ -1,30 +0,0 @@ -#!/usr/local/plan9/bin/rc - -# A web server in rc by maht -# Originally from http://www.proweb.co.uk/~matt/rc/webserver.rc - -ifs=' ' -request=`{sed 1q} - -url=$request(2) -file=`{echo $url | sed 's/http:\/\/[^\/]*//' | tr -d \012} - -if(test -d $file){ - file=$file ^'/index.html' -} -if(test -e $file) { - response='200' -} -if not { - response='404' - file='404.html' -} - -echo 'HTTP/1.1 ' ^$response -echo 'Date: ' `{date} -echo 'Server: rc shell' -echo 'Content-Length: ' `{cat $file | wc -c | tr -d ' '} -echo 'Content-Type: ' `{file -i $file | awk '{ print $2 }'} -echo 'Connection: close' -echo -cat $file diff --git a/bin/corehandlers.rc b/bin/corehandlers.rc @@ -1,157 +0,0 @@ -# Werc builtin handlers - -fn nav_tree { - if(! ~ $#sideBarNavTitle 0) - echo '<p class="sideBarTitle">'$"sideBarNavTitle':</p>' - # Ignore stderr, last path element might be a file that doesn't exist (eg., foo for foo.md) - # /./ to deal with p9p's ls failure to follow dir symlinks otherwise - ls -F $sitedir/./$req_paths_list >[2]/dev/null \ - | { - sed $dirfilter'/\/[^_.\/][^\/]*(\.(md|txt|html)|\/)$/!d; s!^'$sitedir'!!; '$dirclean - if(! ~ $#synth_paths 0) echo $synth_paths | tr ' ' $NEW_LINE - } | sort -u | awk -F/ ' - function p(x, y, s) { for(i=0; i < x-y; i+=1) print s } - BEGIN { lNF=2; print "<ul>" } - { - d = "" - if(match($0, "/$")) - d = "/" - sub("/$", "") # Strip trailing / for dirs so NF is consistent - - p(NF, lNF, "<li><ul>") - p(lNF, NF, "</ul></li>") - lNF = NF - - bname = $NF d - path = $0 d - gsub(/[\-_]/, " ", bname) - - # To avoid false matches add trailing / even for plain files to act as delimiter - pa = path - gsub(/[^\/]$/, "&/", pa) - - if(index(ENVIRON["req_path"] "/", pa) == 1) - print "<li><a href=\"" path "\" class=\"thisPage\">&raquo;<i> " bname "</i></a></li>" - else - print "<li><a href=\"" path "\">&rsaquo; " bname "</a></li>" - } - END { p(lNF, 2, "</ul></li>"); print "</ul>" }' -} - -fn link_bar { - if(~ $1 -t) { - echo '<p class="sideBarTitle">'$2'</p>' - shift; shift - } - echo '<ul>' - while(! ~ $#* 0) { - echo '<li><a href="'$2'">- '$1'</a></li>' - shift; shift - } - echo '</ul>' -} - -fn md_handler { $formatter $1 } - -fn tpl_handler { template $* } - -fn html_handler { - # body states: 0 = no <body> found, 2 = after <body>, 1 = after <body></body>, -1 = after </body> - awk 'gsub(".*<[Bb][Oo][Dd][Yy][^>]*>", "") > 0 {body=2} - gsub("</ *[Bb][Oo][Dd][Yy][^>]*>.*", "") > 0 {print; body=body-1} - body==2 {print} - body==0 {buf=buf "\n" $0} - END {if(body<=0) {print buf}}' < $1 -} - -fn txt_handler { - # Note: Words are not broken, even if they are way beyond 82 chars long - echo '<pre>' - sed 's/</\&lt;/g; s/>/\&gt;/g' < $1 | fmt -l 82 -j - echo '</pre>' -} - -fn dir_listing_handler { - d=`{basename -d $1} - if(~ $#d 0) - d='/' - echo $d|sed 's,.*//,,g; s,/$,,; s,/, / ,g; s/[\-_]/ /g; s,.*,<h1 class="dir-list-head">&</h1> <ul class="dir-list">,' - # Symlinks suck: '/.' forces ls to list the linked dir if $d is a symlink. - ls -F $dir_listing_ls_opts $sitedir$d/. | sed $dirfilter$dirclean | awk '{match($0, "/[^/]*/?$"); l=substr($0, RSTART+1, RLENGTH-1);n=l; gsub(/[\-_]/, " ", n); print "<li><a href=\""l"\">"n"</a></li>"; }' | uniq - echo '</ul>' -} - -fn notices_handler { - for(type in notify_errors notify_notes notify_success) - for(n in $$type) - echo '<div class="'$type'"><b>'$"n'</b></div>' -} - -fn setup_handlers { - - if(test -f $local_path.md) { - local_file=$local_path.md - handler_body_main=(md_handler $local_file) - } - if not if(test -f $local_path.tpl) { - local_file=$local_path.tpl - handler_body_main=(tpl_handler $local_file) - } - if not if(test -f $local_path.html) { - local_file=$local_path.html - handler_body_main=(html_handler $local_file) - } - # Global tpl (eg sitemap.tpl), should take precedence over txt handler! - if not if(test -f tpl^$req_path^.tpl) - # XXX Should we set $local_file for global .tpls? - handler_body_main=(tpl_handler tpl^$req_path^.tpl) - if not if(test -f $local_path.txt) { - local_file=$local_path.txt - handler_body_main=(txt_handler $local_file) - } - - # XXX Should check that $enabled_apps exist in $werc_apps? - # XXX Should split init of apps that provide main handler (eg., blog) and apps that don't (eg., comments)? - if(! ~ $#enabled_apps 0) - for(a in $enabled_apps) - $a^'_init' - - if(! ~ $#handler_body_main 0) - { } # We are done - # Dir listing - if not if(~ $local_path */index) { - handler_body_main=(dir_listing_handler $req_path) - if(test -f $sitedir$req_path'_header.md') { - t=`{get_file_title $sitedir$req_path'_header.md'} - if(! ~ $"t '') - pageTitle=$t - - ll_add handlers_body_head md_handler $sitedir$req_path'_header.md' - } - if(test -f $sitedir$req_path'_footer.md') - ll_add handlers_body_foot md_handler $sitedir$req_path'_footer.md' - } - # Canonize explicit .html urls, the web server might handle this first! - if not if(~ $local_path *.html && test -f $local_path) - perm_redirect `{ echo $req_path|sed 's/.html$//' } - # Fallback static file handler - if not if(test -f $local_path) - static_file $local_path - if not if(~ $req_path /pub/* && test -f .$req_path) - static_file .$req_path - # File not found - if not - setup_404_handler -} - -# This function allows config files to define their own 404 handlers. -fn setup_404_handler { - handler_body_main=(tpl_handler `{get_lib_file 404.tpl}) - echo 'Status: 404 Not Found' - dprint 'NOT FOUND: '$SERVER_NAME^$"REQUEST_URI^' - '^$"HTTP_REFERER^' - '^$"HTTP_USER_AGENT -} - -fn run_handlers { for(h in $*) run_handler $$h } -fn run_handler { $*(1) $*(2-) } - - diff --git a/bin/fltr_cache.rc b/bin/fltr_cache.rc diff --git a/bin/handlers.rc b/bin/handlers.rc @@ -0,0 +1,106 @@ +# Werc builtin handlers + +fn nav_tree { + echo '<ul>' + if(! ~ $#sideBarNavTitle 0) { + if(~ $"req_paths_list /) + echo '<li><a href="/" class="thisPage">'$"sideBarNavTitle'</a></li>' + if not + echo '<li><a href="/">'$"sideBarNavTitle'</a></li>' + } + # Ignore stderr, last path element might be a file that doesn't exist (eg., foo for foo.md) + # /./ to deal with p9p's ls failure to follow dir symlinks otherwise + ls -F $sitedir/./$req_paths_list >[2]/dev/null \ + | { + sed $dirfilter'/\/[^_.\/][^\/]*(\.(md|1)|\/)$/!d; s!^'$sitedir'!!; '$dirclean + if(! ~ $#synth_paths 0) echo $synth_paths | tr ' ' $NEW_LINE + } | sort -u | awk -F/ ' + function p(x, y, s) { for(i=0; i < x-y; i+=1) print s } + BEGIN { lNF=2; } + { + d = "" + if(match($0, "/$")) + d = "/" + sub("/$", "") # Strip trailing / for dirs so NF is consistent + + p(NF, lNF, "<li><ul>") + p(lNF, NF, "</ul></li>") + lNF = NF + + bname = $NF d + path = $0 d + gsub(/[\-_]/, " ", bname) + + # To avoid false matches add trailing / even for plain files to act as delimiter + pa = path + gsub(/[^\/]$/, "&/", pa) + + if(index(ENVIRON["req_path"] "/", pa) == 1) + print "<li><a href=\"" path "\" class=\"thisPage\"> " bname "</a></li>" + else + print "<li><a href=\"" path "\">" bname "</a></li>" + } + END { p(lNF, 2, "</ul></li>"); }' + echo '</ul>' +} + +fn md_handler { $formatter $1 } + +fn tpl_handler { template $* } + +fn man_handler { + echo '<pre>' + $man_formatter $1 + echo '</pre>' +} + +fn dir_listing_handler { + d=`{basename -d $1} + if(~ $#d 0) + d='/' + echo $d|sed 's,.*//,,g; s,/$,,; s,/, / ,g; s/[\-_]/ /g; s,.*,<h1 class="dir-list-head">&</h1> <ul class="dir-list">,' + # Symlinks suck: '/.' forces ls to list the linked dir if $d is a symlink. + ls -F $dir_listing_ls_opts $sitedir$d/. | sed $dirfilter$dirclean | awk '{match($0, "/[^/]*/?$"); l=substr($0, RSTART+1, RLENGTH-1);n=l; gsub(/[\-_]/, " ", n); print "<li><a href=\""l"\">"n"</a></li>"; }' | uniq + echo '</ul>' +} + +fn setup_handlers { + if(test -f $local_path.md) { + local_file=$local_path.md + handler_body_main=(md_handler $local_file) + } + if not if(test -f $local_path.1) { + local_file=$local_path.1 + handler_body_main=(man_handler $local_file) + } + if not if(test -f $local_path.tpl) { + local_file=$local_path.tpl + handler_body_main=(tpl_handler $local_file) + } + if not if(test -f tpl^$req_path^.tpl) + handler_body_main=(tpl_handler tpl^$req_path^.tpl) + if(! ~ $#handler_body_main 0) + { } # We are done + # Dir listing + if not if(~ $local_path */index) + handler_body_main=(dir_listing_handler $req_path) + # Fallback static file handler + if not if(test -f $local_path) + static_file $local_path + if not if(~ $req_path /pub/* && test -f .$req_path) + static_file .$req_path + # File not found + if not + setup_404_handler +} + +# This function allows config files to define their own 404 handlers. +fn setup_404_handler { + handler_body_main=(tpl_handler `{get_tpl_file 404.tpl}) + echo 'Status: 404 Not Found' + dprint 'NOT FOUND: '$SERVER_NAME^$"REQUEST_URI^' - '^$"HTTP_REFERER^' - '^$"HTTP_USER_AGENT +} + +fn run_handlers { for(h in $*) run_handler $$h } +fn run_handler { $*(1) $*(2-) } + diff --git a/bin/util.rc b/bin/util.rc @@ -0,0 +1,117 @@ +############################################################################## +# Useful CGI stuff + +fn dprint { echo $* >[1=2] } + +fn http_redirect { + if(~ $1 http://* https://*) + t=$1 + if not if(~ $1 /*) + t=$"base_url^$1 + if not + t=$"base_url^$"req_path^$1 + echo 'Status: '^$2^' +Location: '^$t^' + +' + exit +} +fn perm_redirect { http_redirect $1 '301 Moved Permanantly' } + +# This seems slightly improve performance, but might depend on httpd buffering behavior. +fn awk_buffer { + awk '{ + buf = buf $0"\n" + if(length(buf) > 1400) { + printf "%s", buf + buf = "" + } + } + END { printf "%s", buf }' +} + +############################################################################## +# Cookies +fn get_cookie { + ifs=';' { co=`{echo $HTTP_COOKIE} } + + # XXX: we might be adding a trailing new line? + # The ' ?' is needed to deal with '; ' inter-cookie delimiter + { for(c in $co) echo $c } | sed -n 's/^ ?'$1'=//p' +} + + +fn static_file { + echo 'Content-Type: '`{select_mime $1} + echo + cat $1 + exit +} + +fn select_mime { + m='text/plain' + if(~ $1 *.css) + m='text/css' + if not if(~ $1 *.ico) + m='image/x-icon' + if not if(~ $1 *.png) + m='image/png' + if not if(~ $1 *.jpg *.jpeg) + m='image/jpeg' + if not if(~ $1 *.gif) + m='image/gif' + if not if(~ $1 *.pdf) + m='application/pdf' + echo $m +} + +############################################################################## +# Generic rc programming helpers + +# Manage nested lists +fn ll_add { + _l=$1^_^$#$1 + $_l=$*(2-) + $1=( $$1 $_l ) +} +# Add to the head: dangerous if you shrink list by hand! +fn ll_addh { + _l=$1^_^$#$1 + $_l=$*(2-) + $1=( $_l $$1 ) +} + + +NEW_LINE=' +' + +############################################################################## +# To be used from config files +fn conf_perm_redirect { + if(~ $#* 1) + perm_redir_to=$1 + if not + ll_addh perm_redir_patterns $1 $2 +} +fn get_tpl_file { + if(test -f tpl/$1) + echo -n tpl/$1 + if not + status='Can''t find tpl file: '$1 +} + +fn template { awk -f bin/template.awk $* | rc $rcargs } + +# File title extraction +fn get_md_title { + sed -n -e '1N; /^.*\n===*$/N; /.*\n===*\n *$/!b' -e 's/\n==*\n//p' < $1 +} + +fn get_file_title { + if (~ $1 *.md) + get_md_title $1 + if not if(~ $1 */) { + if(test -f $1/index.md) + get_md_title $1/index.md + } +} diff --git a/bin/werc.rc b/bin/werc.rc @@ -1,8 +1,6 @@ #!/usr/local/plan9/bin/rc -. ./cgilib.rc -. ./werclib.rc -. ./wercconf.rc -. ./corehandlers.rc +. ./util.rc +. ./handlers.rc . ./fltr_cache.rc cd .. @@ -11,17 +9,14 @@ difs=$ifs # Used to restore default ifs when needed # Expected input: ls -F style, $sitedir/path/to/files/ # <ls -F+x><symlink hack><Useless?><hiden files > -dirfilter='s/\*$//; s,/+\./+,/,g; s,^\./,,; /\/[._][^\/]/d; /'$forbidden_uri_chars'/d; /\/sitemap\.xml$/d; /\/index\.(md|html|txt|tpl)$/d; /\/(robots|sitemap)\.txt$/d; /_werc\/?$/d; ' -dirclean=' s/\.(md|html|txt)$//; ' +dirfilter='s/\*$//; s,/+\./+,/,g; s,^\./,,; /\/[._][^\/]/d; /'$forbidden_uri_chars'/d; /\/sitemap\.xml$/d; /\/index\.(md|tpl)$/d; /\/(robots|sitemap)\.txt$/d; /_werc\/?$/d; ' +dirclean=' s/\.(md|1)$//; ' # Careful, the proper p9p path might not be set until initrc.local is sourced path=(. $PLAN9/bin ./bin /bin /usr/bin) -headers=lib/headers.tpl -res_tail='</body></html>' http_content_type='text/html' ll_add handlers_bar_left nav_tree -werc_apps=( apps/* ) werc_root=`{pwd} sitesdir=sites @@ -30,14 +25,11 @@ sitesdir=sites if(test -f etc/initrc.local) . ./etc/initrc.local -for(a in $werc_apps) - . ./$a/app.rc - fn werc_exec_request { site=$SERVER_NAME base_url=http://$site sitedir=$sitesdir/$site - master_template=`{get_lib_file default_master.tpl} + master_template=`{get_tpl_file master.tpl} current_date_time=`{date} # Note: $REQUEST_URI is not officially in CGI 1.1, but seems to be de-facto @@ -49,12 +41,6 @@ fn werc_exec_request { local_file='' ifs='/' { args=`{echo -n $req_path} } - # Preload post args for templates where cgi's stdin is not accessible - if(~ $REQUEST_METHOD POST) { - load_post_args - login_user - } - if(~ $req_path */index) perm_redirect `{echo $req_path | sed 's,/index$,/,'} @@ -117,8 +103,8 @@ fn werc_exec_request { # XXX Is this never true? because we set pageTitle earlier based on url. if(~ $"pageTitle '') pageTitle=$"siteTitle' '$"siteSubTitle -# if not -# pageTitle=$"pageTitle' | '$"siteTitle' '$"siteSubTitle + if not + pageTitle=$"pageTitle' | '$"siteTitle' '$"siteSubTitle for(h in $extraHttpHeaders) echo $h @@ -131,8 +117,7 @@ fn werc_exec_request { if(~ $REQUEST_METHOD HEAD) exit - template $headers $master_template | awk_buffer - echo $res_tail + template $master_template | awk_buffer } werc_exec_request # >[2]/tmp/wercdebug.log diff --git a/bin/werc_errlog_wrap.rc b/bin/werc_errlog_wrap.rc @@ -1,5 +0,0 @@ -#!/usr/local/plan9/bin/rc - -# This is a wrapper script for broken http servers like recent lighttpd versions which throw away cgi's stderr. - -./werc.rc >>[2]/tmp/wlog.txt diff --git a/bin/wercconf.rc b/bin/wercconf.rc @@ -1,19 +0,0 @@ -# To be used from config files -fn conf_perm_redirect { - if(~ $#* 1) - perm_redir_to=$1 - if not - ll_addh perm_redir_patterns $1 $2 -} - -fn conf_hide_paths { - for(i in $*) - dirfilter=$dirfilter^'/'^`{echo $sitedir$conf_wd$i|sed 's!/+!\\/!g'}^'/d; ' -} - -# Usually will be called from within conf_enable_foo -fn conf_enable_app { - # Note: maybe we should add test -d apps/$1/? - if(! ~ $1 $enabled_apps) - enabled_apps=( $enabled_apps $1 ) -} diff --git a/bin/werclib.rc b/bin/werclib.rc @@ -1,148 +0,0 @@ -fn get_lib_file { - if(! ~ $#sitedir 0 && test -f $sitedir/_werc/lib/$1) - echo -n $sitedir/_werc/lib/$1 - if not if(! ~ $#masterSite 0 && test -f $sitesdir/$masterSite/_werc/lib/$1) - echo -n $sitesdir/$masterSite/_werc/lib/$1 - if not if(test -f lib/$1) - echo -n lib/$1 - if not if(~ $#* 2) - echo -n $2 - if not - status='Can''t find lib file: '$1 -} - -fn template { awk -f bin/template.awk $* | rc $rcargs } - -# Auth code -# TODO: check http://cookies.lcs.mit.edu/pubs/webauth:tr.pdf -allowed_user_chars='[a-zA-Z0-9_]' -# Cookie format: WERC_USER: name:timestamp:hash(name.timestamp.password) -# login_user can't be used from a template because it sets a cookie -fn login_user { - # Note: we set the cookie even if it is already there. - if(get_user $*) - set_cookie werc_user $"logged_user^':0:'^$"logged_password -} - -# Check login status, if called with group arg we check membership too -fn check_user { - get_user - g=($* admin) - _status=$status - if(! ~ $"_status '') - _status=(Not logged in: $"_status) - if not if(! ~ $#* 0 && ! ~ $logged_user $* && ! grep -s '^'^$logged_user^'$' $werc_root/etc/users/$g/members >[2]/dev/null) - _status=(User $logged_user not in: $*) - status=$_status -} - -# If not logged in, try to get user login info from POST or from cookie -fn get_user { - if(~ $#logged_user 0) { - if(~ $#* 2) { - user_name=$1 - user_password=$2 - } - if not if(~ $REQUEST_METHOD POST) - get_post_args user_name user_password - - if(~ $#user_name 0) { - ifs=':' { cu=`{ifs=$difs {get_cookie werc_user} | tr -d $NEW_LINE} } - if(! ~ $#cu 0) { - user_name=$cu(1) - user_password=$cu(3) - } - } - auth_user $user_name $user_password - } - if not - status=() -} - -# Check if user_name and user_password represent a valid user account -# If valid, 'log in' by setting logged_user -fn auth_user { - user_name=$1 - user_password=$2 - - pfile=$werc_root/etc/users/$"user_name/password - if(~ $#user_name 0 || ~ $#user_password 0) - status=('Auth: missing user name or pass: '^$"user_name^' / '^$"user_password) - if not if(! test -f $pfile) - status=('Auth: cant find '^$pfile) - if not if(! test -s $pfile || ! ~ $user_password `{cat $pfile}) - status=('Auth: Pass '$user_password' doesnt match '^`{cat $pfile}) - if not { - logged_user=$user_name - logged_password=$user_password - dprint Auth: success - status=() - } -} - -fn user_controls { - echo User: $"logged_user -} - - -# .md '(meta-)data' extract -fn get_md_file_attr { - sed -n '/^\* '$2': /p; /^\* '$2': /q; /^$/q' < $1 -} - - -# File title extraction -fn get_md_title { - #sed 's/^(................................................................[^ ]*).*$/\1/g; 1q' < $1 - sed -n -e '1N; /^.*\n===*$/N; /.*\n===*\n *$/!b' -e 's/\n==*\n//p' < $1 -} - -fn get_html_title { - t=`{sed -n '32q; s/^.*<[Tt][Ii][Tt][Ll][Ee]> *([^<]+) *(<\/[Tt][Ii][Tt][Ll][Ee]>.*)?$/\1/p' < $1} - - # As a backup we might want to pick the first 'non-tag' text in the file with: - if(~ $"t '') - t=`{sed -n -e 's/^[ ]*(<[^>]+>)*([^<]+).*/\2/p; 32q' < $1 | sed 1q} - - echo $t -} - -fn get_file_title { - if (~ $1 *.md) - get_md_title $1 - if not if(~ $1 *.html) - get_html_title $1 - if not if(~ $1 */) { - if(test -f $1/index.md) - get_md_title $1/index.md - if not if(test -f $1/index.html) - get_html_title $1/index.html - } -} - - -########################################################################## -########################################################################## -#app_blog_methods = ( _post index.rss ) -#fn app_blog__post { -# echo -#} -# -#app_blog___default { -# if (~ $blog) -# call_app blogpost -#} -# -## -- -#app_blogpost_methods = ( comment _edit ) -# -#fn app_blogpost_comment { -# call_app comments -#} -# -## -- -#app_comments_methods = ( _post _edit ) -# -#fn app_comments___default { -# -#} diff --git a/etc/initrc b/etc/initrc @@ -1,40 +1,7 @@ -# This file contains the default werc settings. -# -# DO NOT EDIT, to customize copy to etc/initrc.local and edit at will. -# -# Some settings can also be set for a specific site or directory in their -# respective _werc/config or their $masterSite/_werc/config file. - # General options - -# Location of your Plan 9 from User Space installation (usually /usr/local/plan9) plan9port=$PLAN9 -#plan9port=/usr/local/plan9 - -# If you use 9base, it should point to your 9base root, try for example: -#plan9port=/usr/lib/9base # This is the default 9base install path in Debian. - -# If rc is not installed as /usr/local/plan9/bin/rc you will also need to change -# the #! line in bin/werc.rc! - -# Path, make sure the plan9port /bin directory is included before /bin -# Keep '.' in path! It is needed. path=($plan9port/bin . ./bin ./bin/contrib /bin /usr/bin) - -# Set this to your favorite markdown formatter, eg., markdown.pl (fltr_cache -# takes as an argument a filter, in the default configuration markdown.pl, that -# caches output) Note that some werc components assume a markdown-like -# formatter, but all major functionality should should be formatter agnostic. -#formatter=(md2html.awk) -formatter=(fltr_cache markdown.pl) - -# Enable debugging, to disable set to () -debug=true - -# Globally enabled apps -enabled_apps=( ) - -# Default site variables, must be set in initrc.local or _werc/config, only siteTitle is required. -#masterSite=cat-v.org # Not required! -#siteTitle='cat-v' -#siteSubTitle='Considered harmful' +formatter=(fltr_cache markdown) +man_formatter=(troff -N -man) +debug=() +sitesdir='/var/www/sites' diff --git a/etc/users/GROUP_AND_USER_ACCOUNTS b/etc/users/GROUP_AND_USER_ACCOUNTS @@ -1 +0,0 @@ -This is just a dummy file to force hg to preserve this directory that is used to store user and group account information. diff --git a/lib/404.tpl b/lib/404.tpl @@ -1,12 +0,0 @@ -<h1>The requested document at '<i>%($base_url$"req_path%)</i>' doesn't exist</h1> - -% # Google Enhanced 404 pages: http://www.google.com/support/webmasters/bin/answer.py?answer=93644 -<script type="text/javascript"> - var GOOG_FIXURL_LANG = 'en'; - var GOOG_FIXURL_SITE = '%($base_url%)/'; -</script> -<script type="text/javascript" - src="http://linkhelp.clients.google.com/tbproxy/lh/wm/fixurl.js"></script> - -<h4>Or take a look at the <a href="/sitemap">sitemap</a>.</h4> -<hr> diff --git a/lib/default_master.tpl b/lib/default_master.tpl @@ -1,35 +0,0 @@ -<div id="header"> - <div class="superHeader"> -% cat `{ get_lib_file top_bar.inc } - </div> - - <div class="midHeader"> - <h1 class="headerTitle"><a href="/">%($"siteTitle%) <span id="headerSubTitle">%($"siteSubTitle%)</span></a></h1> - </div> - - <div class="subHeader"><br></div> -</div> - -% if(! ~ $#handlers_bar_left 0) { - <div id="side-bar"> -% for(h in $handlers_bar_left) { - <div> -% run_handler $$h - </div> -% } - </div> -% } - -<div id="main-copy"> - -% run_handlers $handlers_body_head - -% run_handler $handler_body_main - -% run_handlers $handlers_body_foot - -</div> - -<div id="footer"> -% cat `{ get_lib_file footer.inc } -</div> diff --git a/lib/footer.inc b/lib/footer.inc @@ -1,6 +0,0 @@ -<div class="left"><a href="http://werc.cat-v.org/">Powered by werc</a></div> -<!-- TODO Maybe should add a programatically generated google search box --> -<div class="right"><a href="/_users/login">User Login</a></div> - -<br> -<br class="doNotDisplay doNotPrint"> diff --git a/lib/headers.tpl b/lib/headers.tpl @@ -1,29 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> - - <title>%($pageTitle%)</title> - - <link rel="stylesheet" href="/pub/style/style.css" type="text/css" media="screen, handheld" title="default"> - <link rel="shortcut icon" href="/favicon.ico" type="image/vnd.microsoft.icon"> -% if(test -f $sitedir/_werc/pub/style.css) -% echo ' <link rel="stylesheet" href="/_werc/pub/style.css" type="text/css" media="screen" title="default">' - - <meta charset="UTF-8"> -% # Legacy charset declaration for backards compatibility with non-html5 browsers. - <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> - -% if(! ~ $#meta_description 0) -% echo ' <meta name="description" content="'$"meta_description'">' -% if(! ~ $#meta_keywords 0) -% echo ' <meta name="keywords" content="'$"meta_keywords'">' - -% h = `{get_lib_file headers.inc} -% if(! ~ $#h 0) -% cat $h - - %($"extraHeaders%) - -</head> -<body> - diff --git a/lib/top_bar.inc b/lib/top_bar.inc @@ -1,16 +0,0 @@ - <div class="left"> - <a href="http://gsoc.cat-v.org">gsoc</a> | - <a href="http://doc.cat-v.org">doc archive</a> | - <a href="http://repo.cat-v.org">software repo</a> | - <a href="http://ninetimes.cat-v.org">ninetimes</a> | - <a href="http://harmful.cat-v.org">harmful</a> | - <a href="http://9p.cat-v.org/">9P</a> | - <a href="http://cat-v.org">cat-v.org</a> - </div> - - <div class="right"> - <span class="doNotDisplay">Related sites:</span> - | <a href="http://cat-v.org/update_log">site updates</a> - | <a href="/sitemap">site map</a> - </div> - diff --git a/pub/default_favicon.ico b/pub/default_favicon.ico Binary files differ. diff --git a/pub/style.css b/pub/style.css @@ -0,0 +1,155 @@ +body { + background-color: #eee; + color: #333; + font-family: Helvetica, Verdana, Arial, 'Liberation Sans', FreeSans, sans-serif; + padding: 0; + margin: 0; +} + +a { + color: #057; + text-decoration: none; +} + +a:hover { + color: #666; +} + +#menu { + clear: both; + color: #ccc; + background-color: #057; + padding: 0.7ex; + font-size: 84%; +} + +#menu a { + padding: 0.5ex 1ex 0.5ex 1ex; + color: #fff; +} + +#menu a:hover { + color: #ccc; +} + +#header { + clear: both; + color: #666; + text-shadow: 1px 1px #fff; + font-size: 1.7em; + padding: 0.7ex 0.7ex 0.7ex 0.7em; + border-top: 1px solid #ccc; +} + +#header a { + color: #666; +} + +h1 { + margin: 1em 1ex 0.5ex 0; + font-size: 1.4em; +} + +h2 { + margin: 1em 1ex 0.5ex 0; + font-size: 1.3em; +} + +h3 { + margin: 1em 1ex 0.5ex 0; + font-size: 1.2em; +} + +h4 { + margin: 1em 1ex 0.5ex 0; + font-size: 1.1em; +} + +#headerSubTitle { + font-size: 0.8em; + font-style: italic; + margin-left: 1em; +} + +#content { + clear: both; + margin: 0; + padding: 0; + background-color: #fff; + overflow: hidden; + border-top: 1px solid #ccc; + border-bottom: 1px solid #ccc; +} + +#nav { + background-color: #fff; + float: left; + margin: 0 1px 0 0; + padding: 1em 0; + border-right: 1px dotted #ccc; + width: 200px; +} + +#nav ul { + margin: 0; + padding: 0; +} + +#nav li { + list-style: none; + padding: 0; + margin: 0; +} + +#nav li ul { + padding-left: 0.6em !important; +} + +#nav li a { + color: #057; + display: block; + margin: 0; + padding: 0.8ex 2em 0.8ex 1em; +} + +#nav li a:hover { + background: #eee; +} + +#nav li a.thisPage { + color: #333; + font-weight: bold; + font-style: italic; +} + +#main { + text-align: justify; + margin: 0 0 0 200px; + padding: 1.5em; + max-width: 50em; +} + +#ads { + float:right; + padding: 1em; +} + +#footer { + clear: both; + color: #666; + font-size: 84%; + padding: 1em; + margin: 0 0 1.5em 0; +} + +.left { + float: left; + margin: 0; + padding: 0; +} + +.right { + float: right; + margin: 0; + padding: 0; +} diff --git a/pub/style/imgs/sgl.png b/pub/style/imgs/sgl.png Binary files differ. diff --git a/pub/style/sinorca-screen-alt.css b/pub/style/sinorca-screen-alt.css @@ -1,292 +0,0 @@ -/*********************************************** - * TITLE: Sinorca Alterative Screen Stylesheet * - * URI : sinorca/sinorca-screen-alt.css * - * MODIF: 2003-May-13 18:48 +0800 * - ***********************************************/ - - -/* ##### Common Styles ##### */ - -body { - color: black; - background-color: white; - font-family: verdana, helvetica, arial, sans-serif; - font-size: 71%; /* Enables font size scaling in MSIE */ - margin: 0; - padding: 0; -} - -html > body { - font-size: 8.5pt; -} - -acronym, .titleTip { - border-bottom: 1px dotted rgb(153,153,153); - cursor: help; - margin: 0; - padding: 0 0 0.4px 0; -} - -.doNotDisplay { - display: none; -} - -.smallCaps { - font-size: 110%; - font-variant: small-caps; -} - - -/* ##### Header ##### */ - -.superHeader { - color: white; - background-color: rgb(100,135,220); - height: 2em; -} - -.superHeader a { - color: white; - background-color: transparent; - text-decoration: none; - font-size: 91%; - margin: 0; - padding: 0 0.5ex 0 0.25ex; -} - -.superHeader a:hover { - text-decoration: underline; -} - -.superHeader .left { - position: absolute; - left: 1.5mm; - top: 0.75ex; -} - -.superHeader .right { - position: absolute; - right: 1.5mm; - top: 0.75ex; -} - -.midHeader { - color: rgb(39,78,144); - background-color: rgb(140,170,230); -} - -.headerTitle { - font-size: 337%; - font-weight: normal; - margin: 0 0 0 4mm; - padding: 0.25ex 0; -} - -.subHeader { - color: white; - background-color: rgb(0,51,153); - margin: 0; - padding: 1ex 1ex 1ex 1.5mm; -} - -.subHeader a { - color: white; - background-color: transparent; - text-decoration: none; - font-weight: bold; - margin: 0; - padding: 0 0.75ex 0 0.5ex; -} - -.subHeader a:hover { - text-decoration: underline; -} - -.superHeader .highlight, .subHeader .highlight { - color: rgb(253,160,91); - background-color: transparent; -} - - -/* ##### Side Boxes ##### */ - -#side-bar { - width: 14em; - margin: 2.5em 0 0 1.25mm; - float: left; - clear: left; -} - -body > #side-bar { - margin-left: 2.5mm; /* Circumvents a rendering bug in MSIE (6.0) */ -} - -.sideBarTitle { - color: white; - background-color: rgb(100,135,220); - font-weight: bold; - margin: 0; - padding: 0.4ex 0 0.4ex 0.6ex; -} - -#side-bar ul { - list-style-type: none; - list-style-position: outside; - margin: 0; - padding: 0 0 2.25em 0; -} - -#side-bar li { - margin: 0; - padding: 0.1ex 0; /* Circumvents a rendering bug (?) in MSIE (6.0) */ -} - -#side-bar a, .thisPage { - color: rgb(0,102,204); - background-color: transparent; - text-decoration: none; - font-weight: bold; - margin: 0; - padding: 1.3ex 2ex; - display: block; -} - -.thisPage { - color: black; - background-color: transparent; -} - -#side-bar a:hover { - color: white; - background-color: rgb(100,135,220); - text-decoration: none; -} - -.sideBarText { - line-height: 1.5em; - margin: 0 0 2.5em 0; - padding: 1ex 0.5ex 0 0.5ex; - display: block; -} - -.sideBarText + .sideBarText { /* Not recognised by MSIE (6.0) */ - margin-top: -1.5em; -} - -#side-bar .sideBarText a { - text-decoration: underline; - font-weight: normal; - 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 { - color: black; - background-color: transparent; - text-align: justify; - line-height: 1.5em; - margin: -1em 0 0 15em; - padding: 0.5mm 5mm 5mm 5mm; -} - -#bodyText { - margin: 0 0 0 15.5em; - padding: 2mm 5mm 2mm 5mm; -} - - -#main-copy p { - margin: 1em 1ex 2em 1ex; - padding: 0; -} - -#main-copy a { - color: rgb(0,102,204); - background-color: transparent; - text-decoration: underline; -} - -#main-copy a:hover { - text-decoration: none; -} - -#main-copy h1 { - 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: 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); - font-size: 91%; - margin: 0; - padding: 1em 2.5mm 2.5ex 2.5mm; - clear: both; -} - -#footer .left { - text-align: left; - line-height: 1.45em; - float: left; - clear: left; -} - -#footer .right { - text-align: right; - line-height: 1.45em; -} - -#footer a { - color: white; - background-color: transparent; - text-decoration: underline; -} - -#footer a:hover { - text-decoration: none; -}- \ No newline at end of file diff --git a/pub/style/style.css b/pub/style/style.css @@ -1,330 +0,0 @@ -/* Default werc style */ - -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; -} diff --git a/pub/style/style_old.css b/pub/style/style_old.css @@ -1,330 +0,0 @@ -/* Old Default style */ -/* ##### Common Styles ##### */ - -body { - color: black; - XXXbackground-color: rgb(240,240,240); - background-color: white; - font-family: verdana, helvetica, arial, sans-serif; - font-size: 71%; /* Enables font size scaling in MSIE */ - margin: 0; - padding: 0; -} - -html > body { - font-size: 8.5pt; -} - -acronym, .titleTip { - border-bottom: 1px dotted rgb(153,153,153); - cursor: help; - margin: 0; - padding: 0 0 0.4px 0; -} - -.doNotDisplay { - display: none; -} - -.smallCaps { - font-size: 110%; - font-variant: small-caps; -} - - -/* ##### Header ##### */ - -.superHeader { - color: white; - background-color: rgb(100,135,220); - height: 2em; -} - -.superHeader a { - color: white; - background-color: transparent; - text-decoration: none; - font-size: 91%; - margin: 0; - padding: 0 0.5ex 0 0.25ex; -} - -.superHeader a:hover { - text-decoration: underline; -} - -.superHeader .left { - position: absolute; - left: 1.5mm; - top: 0.75ex; -} - -.superHeader .right { - position: absolute; - right: 1.5mm; - top: 0.75ex; -} - -.midHeader { - color: rgb(39,78,144); - background-color: rgb(140,170,230); - border: solid 0 black; - border-width: 0.3em 0; -} - -.headerTitle { - color: black; - font-size: 337%; - font-weight: normal; - margin: 0 0 0 4mm; - padding: 0.25ex 0; -} -#headerSubTitle { - font-size: 50%; - font-style: italic; -} - -.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; - text-decoration: none; - font-weight: bold; - margin: 0; - padding: 0 0.75ex 0 0.5ex; -} - -.subHeader a:hover { - text-decoration: underline; -} - -.superHeader .highlight, .subHeader .highlight { - color: rgb(253,160,91); - background-color: transparent; -} - - -/* ##### Side Bar ##### */ - -#side-bar { - width: 15em; - float: left; - clear: left; - border-right: 1px solid rgb(153,153,153); -} - -#side-bar div { - border-bottom: 1px solid rgb(153,153,153); -} - -.sideBarTitle { - font-weight: bold; - margin: 0 0 0.5em 2.5mm; - padding: 1em 0 0 0; -} - -#side-bar ul { - list-style-type: none; - list-style-position: outside; - margin: 0; - padding: 0 0 1.1em 0; -} - -#side-bar li { - margin: 0; - padding: 0.1ex 0; /* Circumvents a rendering bug (?) in MSIE 6.0 */ -} - -#side-bar a, .thisPage { - color: rgb(0,102,204); - background-color: transparent; - XXXtext-decoration: none; - margin: 0; - padding: 0.55em 1ex 0.55em 5mm; - display: block; -} - -.thisPage { - color: black; - background-color: white; - padding-left: 5mm; - XXXborder-top: 1px solid rgb(153,153,153); - XXXborder-bottom: 1px solid rgb(153,153,153); - font-weight: 600; -} - -#side-bar a:hover { - color: white; - background-color: rgb(100,135,220); - 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 { - text-decoration: underline; - margin: 0; - padding: 0; - display: inline; -} - -#side-bar .sideBarText a:hover { - color: rgb(0,102,204); - background-color: transparent; - text-decoration: none; -} - -.lighterBackground { - color: inherit; - background-color: white; -} - - -/* ##### Main Copy ##### */ - -#main-copy { - max-width: 90em; - color: black; - background-color: white; - text-align: justify; - line-height: 1.5em; - margin: 0 0 0 15em; - padding: 0.5mm 5mm 5mm 5mm; - border-left: 1px solid rgb(153,153,153); -} - -#main-copy p { - margin: 1em 1ex 2em 1ex; - padding: 0; -} - -#main-copy a { - color: rgb(0,102,204); - background-color: transparent; - text-decoration: underline; -} - -#main-copy a:hover { - text-decoration: none; -} - -#main-copy h1 { - color: white; - background-color: rgb(100,135,220); - font-size: 100%; - font-weight: bold; - margin: 3em 0 0 0; - padding: 0.5ex 0 0.5ex 1ex; -} - -#main-copy .topOfPage { - color: white; - background-color: transparent; - font-size: 91%; - font-weight: bold; - text-decoration: none; - margin: 2.5ex 1ex 0 0; /* For MSIE */ - padding: 0; - float: right; -} - -#main-copy > .topOfPage { - margin: 2.75ex 1ex 0 0; /* For fully standards-compliant user agents */ -} - -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); - font-size: 91%; - margin: 0; - padding: 1em 2.5mm 2.5ex 2.5mm; - clear: both; -} - -#footer .left { - line-height: 1.45em; - float: left; - clear: left; -} - -#footer .right { - text-align: right; - line-height: 1.45em; -} - -#footer a { - color: white; - background-color: transparent; - text-decoration: underline; -} - -#footer a:hover { - text-decoration: none; -} - - -/* GENERAL */ -/* Spam */ -.spam { - text-align: center; -} - -/* Tables */ -table { - border: solid 1px black; -} -th { - background-color: #abc; - border: solid 1px black; -} -td { - background-color: #def; - border: solid 1px black; -} - -hr { - border-width: 0px 0px 0.1em 0px; - border-color: black; -} - -.spam table, .spam th, .spam td { - border: none; -} - -/* Code */ -pre { - margin-left: 2em; -} - - diff --git a/pub/style1.css b/pub/style1.css @@ -0,0 +1,156 @@ +body { + background-color: #333; + color: #ddd; + font-family: Helvetica, Verdana, Arial, 'Liberation Sans', FreeSans, sans-serif; + padding: 0; + margin: 0; +} + +a { + color: #6af; + text-decoration: none; +} + +a:hover { + color: #999; +} + +#menu { + clear: both; + color: #ccc; + background-color: #057; + padding: 0.7ex; + font-size: 84%; +} + +#menu a { + padding: 0.5ex 1ex 0.5ex 1ex; + color: #eee; +} + +#menu a:hover { + color: #ccc; +} + +#header { + clear: both; + color: #ddd; + text-shadow: 1px 1px #000; + font-size: 1.7em; + padding: 0.7ex 0.7ex 0.7ex 0.7em; + border-top: 1px solid #444; +} + +#header a { + color: #ddd; +} + +h1 { + margin: 1em 1ex 0.5ex 0; + font-size: 1.4em; +} + +h2 { + margin: 1em 1ex 0.5ex 0; + font-size: 1.3em; +} + +h3 { + margin: 1em 1ex 0.5ex 0; + font-size: 1.2em; +} + +h4 { + margin: 1em 1ex 0.5ex 0; + font-size: 1.1em; +} + +#headerSubTitle { + font-size: 0.8em; + font-style: italic; + margin-left: 1em; +} + +#content { + clear: both; + margin: 0; + padding: 0; + background-color: #222; + overflow: hidden; + border-top: 1px solid #444; + border-bottom: 1px solid #444; +} + +#nav { + background-color: #222; + float: left; + margin: 0 1px 0 0; + padding: 1em 0; + border-right: 1px dotted #444; + width: 200px; +} + +#nav ul { + margin: 0; + padding: 0; +} + +#nav li { + list-style: none; + padding: 0; + margin: 0; +} + +#nav li ul { + padding-left: 0.6em !important; +} + +#nav li a { + color: #6af; + display: block; + margin: 0; + padding: 0.8ex 2em 0.8ex 1em; +} + +#nav li a:hover { + background: #057; + color: #ddd; +} + +#nav li a.thisPage { + color: #ddd; + font-weight: bold; + font-style: italic; +} + +#main { + margin: 0 0 0 200px; + padding: 1.5em; + max-width: 50em; + text-align: justify; +} + +#ads { + float:right; + padding: 1em; +} + +#footer { + clear: both; + color: #ddd; + font-size: 84%; + padding: 1em; + margin: 0 0 1.5em 0; +} + +.left { + float: left; + margin: 0; + padding: 0; +} + +.right { + float: right; + margin: 0; + padding: 0; +} diff --git a/sites/CREATE-SITE-DIRECTORIES-HERE b/sites/CREATE-SITE-DIRECTORIES-HERE diff --git a/sites/default.cat-v.org/_werc/lib/footer.inc b/sites/default.cat-v.org/_werc/lib/footer.inc @@ -1,29 +0,0 @@ -<br class="doNotDisplay doNotPrint" /> - -<div class="left"><a href="http://werc.cat-v.org/">Powered by werc</a></div> - -<div class="right"> -<form action="http://www.google.com/cse" id="cse-search-box" style="display: inline"> - <div style="display: inline"> - <input type="hidden" name="cx" value="partner-pub-2060328396151526:ea9sar-xttn" /> - <input type="hidden" name="ie" value="UTF-8" /> - <input type="text" name="q" size="32" /> - <input type="submit" name="sa" value="Search" /> - </div> -</form> -<script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&lang=en"></script></div> - - -<script type="text/javascript"> -var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www."); -document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E")); -</script> -<script type="text/javascript"> -try { -var pageTracker = _gat._getTracker("UA-1220719-1"); -pageTracker._setDomainName("cat-v.org"); -pageTracker._trackPageview(); - -var pageTracker2 = _gat._getTracker("UA-1220719-12"); -pageTracker2._trackPageview(); -} catch(err) {}</script> diff --git a/sites/default.cat-v.org/_werc/lib/headers.inc b/sites/default.cat-v.org/_werc/lib/headers.inc @@ -1,5 +0,0 @@ -<meta name="verify-v1" content="6zEoK0WMlnLmIS/w7Pnh6+srZECHsvnMGN0kQmowSGk=" /> -<meta name="google-site-verification" content="z5zCyEitNLNZmhVblsogrEiy6Acf0UZROsFMtLjioN4" /> -<META name="y_key" content="49dff3fad5352458"><META name="y_key" content="5dc40bfee9494e98"><META name="y_key" content="b60a53d1fa98f4c8"> -<meta name="msvalidate.01" content="5008C6E6B172BEB1F43E770296C3D560" /> -<meta name="alexaVerifyID" content="l1vBNiKWqe9hCZhp0jV8OKPyjps" /> diff --git a/sites/default.cat-v.org/_werc/lib/top_bar.inc b/sites/default.cat-v.org/_werc/lib/top_bar.inc @@ -1,25 +0,0 @@ - <div class="left"> - <a href="http://quotes.cat-v.org">quotes</a> | - <a href="http://doc.cat-v.org">docs</a> | - <a href="http://repo.cat-v.org">repo</a> | - <a href="http://go-lang.cat-v.org">golang</a> | - <a href="http://sam.cat-v.org">sam</a> | - <a href="http://man.cat-v.org">man</a> | - <a href="http://acme.cat-v.org">acme</a> | - <a href="http://glenda.cat-v.org">Glenda</a> | - <a href="http://ninetimes.cat-v.org">9times</a> | - <a href="http://harmful.cat-v.org">harmful</a> | - <a href="http://9p.cat-v.org/">9P</a> | - <a href="http://cat-v.org">cat-v.org</a> - </div> - - <div class="right"> - - <span class="doNotDisplay">Related sites:</span> - | <a href="http://cat-v.org/update_log">site updates</a> - | <a href="/sitemap">site map</a> | - - <script type="text/javascript">var addthis_disable_flash = true; var addthis_pub="uriell";</script> - <a href="http://www.addthis.com/bookmark.php?v=20" onmouseover="return addthis_open(this, '', '[URL]', '[TITLE]')" onmouseout="addthis_close()" onclick="return addthis_sendto()"><img src="http://s7.addthis.com/static/btn/lg-share-en.gif" width="125" height="16" alt="Bookmark and Share" style="border:0"/></a><script type="text/javascript" src="http://s7.addthis.com/js/200/addthis_widget.js"></script> - </div> - diff --git a/sites/tst.cat-v.org/_werc/config b/sites/tst.cat-v.org/_werc/config @@ -1,2 +0,0 @@ -masterSite=default.cat-v.org -siteTitle='Werc Test Suite' diff --git a/sites/tst.cat-v.org/apps/blagh/_werc/config b/sites/tst.cat-v.org/apps/blagh/_werc/config @@ -1,3 +0,0 @@ -conf_enable_blog -conf_blog_pubsubdub_hub='http://pubsubhubbub.appspot.com/' - diff --git a/sites/tst.cat-v.org/apps/bridge/a/_werc/config b/sites/tst.cat-v.org/apps/bridge/a/_werc/config @@ -1 +0,0 @@ -conf_enable_comments -a diff --git a/sites/tst.cat-v.org/index.md b/sites/tst.cat-v.org/index.md @@ -1,4 +0,0 @@ -Werc Test Suite -=============== - -This site contants sample/test content for the werc web anti-framework. diff --git a/sites/tst.cat-v.org/titles/dashed-title.md b/sites/tst.cat-v.org/titles/dashed-title.md @@ -1,3 +0,0 @@ -This page has an all-lower case dashed title. - -The correct page title should be: `Dashed Title`. diff --git a/sites/tst.cat-v.org/titles/under_title.md b/sites/tst.cat-v.org/titles/under_title.md @@ -1,3 +0,0 @@ -This page has an all-lower case underscore separated title. - -The correct page title should be: `Under Title`. diff --git a/sites/werc.cat-v.org/_werc/config b/sites/werc.cat-v.org/_werc/config @@ -1,7 +0,0 @@ -masterSite=default.cat-v.org -siteTitle='werc' -siteSubTitle='Bringing minimalism and sanity to the web' -conf_enable_comments -conf_enable_wiki - -#ll_add handlers_body_head echo '<div style="text-align:right"><script type="text/javascript" src="http://www.reddit.com/r/programming/button.js?t=1"></script></div>' diff --git a/sites/werc.cat-v.org/apps/_footer.md b/sites/werc.cat-v.org/apps/_footer.md @@ -1,10 +0,0 @@ -External Apps -============= - -This are some apps developed by werc users, to install them put them in your werc's `apps/` dir and enable them from any config file as usual. - -* [Xibit](http://xibit.soul9.org/): an image gallery app by written by soul9. -* [SMAK](http://www.anarchyinthetubes.com/hg/smak/): a "very simple" image gallery by yiyus. -* [hgwerc](http://www.anarchyinthetubes.com/hg/hgwerc/): a wrapper around the mercurial web interface to integrate it into werc sites, also by yiyus. -* [scrappydog](http://code.google.com/p/scrappydog/): A werc based online scrapbook by maht. -* [flip](http://www.anarchyinthetubes.com/hg/flip/): A web interface to view PDFs, by yiyus. diff --git a/sites/werc.cat-v.org/apps/_header.md b/sites/werc.cat-v.org/apps/_header.md @@ -1,5 +0,0 @@ -Werc Apps -========= - -Werc includes the following 'apps' by default that any site can enable usually by executing a function of the form `conf_enable_myapp` in any given `_werc/config` file. - diff --git a/sites/werc.cat-v.org/apps/blagh/index.md b/sites/werc.cat-v.org/apps/blagh/index.md @@ -1,59 +0,0 @@ -Blagh - A Blogging engine for people who hate blogs -=================================================== - -Blagh is a werc app that implements a blogging engine. - -Some features include: - -* File based, database free. -* History browsing. -* Atom and RSS feeds. -* Server-side feed 'aggregation' (merge multiple blogs into a single one). -* Comments using [bridge](../bridge/) -* Markdown formatting. - -Possible alternative names: Blag, Blah, Bragg. - -Posting -------- - -New pots can be created in at least two different ways: using the web interface (if you have logged in and your user or groups are in `$conf_blog_editors`) or from the command line using the script at `bin/aux/bpst.rc`. This script will, optionally, take a file as an argument using the `-f` switch. It will open that file in your `$EDITOR` or create a new temporary file if the `-f` switch is omitted. When you have finished editing the file, the script will call `ispell` (so you may want to install that as well) to check for spelling errors. Once that has completed a new directory structure will be created in your blog's root directory as a hidden folder named after the current year (as detected by `date`). You can inspect this directory structure for continuity and `mv` it to unhide it when you are satisfied. You are encouraged to read the source of that very simple script, and you shall see that it is trivial to create new posts by simply using `mkdir` and `echo`. - -Configuration options ---------------------- - -This are options you can set in your _werc/config - -### `conf_enable_blog` *[blog dirs]* - -Setup a blog in this dir. By default the blog contents will only include posts stored in this dir, if you pass any arguments the posts in the various dirs will be aggregated in this feed. - -Examples: - - # This will setup a blog in this dir that includes only posts in this dir. - conf_enable_blog - - # This will create a blog that aggregates all the posts in all blog dirs in any users/ sub dir. - conf_enable_blog users/*/blog - -### `conf_blog_editors`=(*groups or users that will be allowed to make new blog posts*) - -This is optional and by default set to the 'blog-editors' group. - -### `conf_max_lines_per_post=`*[integer]* - -This option may be added using the patch linked bellow. It defaults to `7` which **should** only include the page heading and the first two paragraphs of each post on the main blogroll(?) page. This makes many assumptions that should be noted. It just removes everything from `conf_max_lines_per_post` to the end of the file. Traditionally, line 1 is the H1 title and line 2 is the line of = required to tell mardown of it's importance. This then assumes that each paragraph is on a single line, which is not enforced by markdown. See it in action at <http://blog.senet.us> - -[blagh-91a4597480a7-conf\_max\_lines\_per\_post.diff](http://senet.us/blagh-91a4597480a7-conf_max_lines_per_post.diff) (1.2K) (20100114) - -**Author**: J Thigpen (cdarwin) <darwin@senet.us> - -See also: - -* To edit blog posts you can use the functionality provided by [the dirdir app](../dirdir/). -* Commenting can be handled by [the bridge app](../bridge/). - - - - - diff --git a/sites/werc.cat-v.org/apps/bridge/index.md b/sites/werc.cat-v.org/apps/bridge/index.md @@ -1,13 +0,0 @@ -Bridge -====== - -Bridge is a comments/forum application for werc, which lets people post comments related to any existing document/element. - - -Configuration options ---------------------- - -### `conf_enable_comments` [-n] [*users and groups allowed to comment*] - -This will enable comments in this directory and all sub-directories. `-n` enables commenting by unregistered users (their posts will be set aside for review and approval by administrators). - diff --git a/sites/werc.cat-v.org/apps/dirdir/index.md b/sites/werc.cat-v.org/apps/dirdir/index.md @@ -1,48 +0,0 @@ -DirDir - A directory-oriented WikiWiki -====================================== - -DirDir is the next generation [diri wiki](http://repo.cat-v.org/diri/), now implemented on top of werc and -taking advantage of its user, site management frameworks and other -infrastructure. - -Features --------- - -DirDir is still somewhat experimental, but already all features diri had, plus some extras thanks to werc's power: - - * Hierarchical organization. - * Markdown formatting. - * Easily customizable templates - * Simple and fine grained user permisions system. - * Completely database free. - * All needed to setup diridiri is to set a flag in your _werc/config file. - * Automatically wiki-fy existing werc documents. - * Implemented in about two dozen lines of rc scripts. - - -Documentation -------------- - -Just login, go to any page, and click the `Edit` button. - -To create a new page, go to the address where you want to create the new page, click `Edit`, enter the initial contents, `Save`, and you are done. - - -Status ------- - -Mostly usable, all basic features already implemented in the latest werc source -tree. - - -TODO ----- - -* Do some markdown preprocessing, for example: `[[Foo Bar]]` -> `[Foo Bar](foo-bar)` - - -About the name --------------- - -DirDir is a pun on its predecessor diri and WikiWiki, and [Dirdir is also the title of a novel](http://www.amazon.com/gp/product/0879974788?ie=UTF8&tag=catv-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0879974788) by science fiction and literature grand master [Jack Vance](http://www.amazon.com/gp/redirect.html?ie=UTF8&location=http%3A%2F%2Fwww.amazon.com%2Fs%3Fie%3DUTF8%26redirect%3Dtrue%26search-type%3Dss%26index%3Dbooks%26ref%3Dntt%255Fathr%255Fdp%255Fsr%255F1%26field-author%3DJack%2520Vance&tag=catv-20&linkCode=ur2&camp=1789&creative=39095). - diff --git a/sites/werc.cat-v.org/apps/wman/index.md b/sites/werc.cat-v.org/apps/wman/index.md @@ -1,34 +0,0 @@ -wman - A Web Interface to Man Pages -=================================== - -Wman is an app that allows you to export Unix and Plan 9-style man pages. It -can do this directly, without need to generate static html versions and will -automatically pick updates and new man pages. - -It is also fairly smart in generating links for man page references. - -Configuration -------------- - -To display a collection of man pages in a desired path you can use the following config directive: - - conf_enable_wman /usr/share/man - -This will allow you to browse the man pages under /usr/share/man. - -For man pages organized in the traditional unix structure `manN/foo.N` where N is the section number, set in your config file: - - wman_unix_mode=1 - -Demo ----- - -For a demo of this app see [man.cat-v.org](http://man.cat-v.org). - -TODO ----- - -* We don't handle compressed man pages, but this should be trivial to add. -* Unix systems might use different macros for their man pages. -* Search (using keywords? Google? grep?) -* Inferno contains man pages named like 'foo-0intro', which are refered as foo-intro(X), should automatically add (or remove) the extra '0' (Examples: sys-intro(2) and draw-intro(2)). diff --git a/sites/werc.cat-v.org/development/index.md b/sites/werc.cat-v.org/development/index.md @@ -1,21 +0,0 @@ -Werc Development -================ - -The latest dev code is available in the werc mercurial repo: http://hg.cat-v.org/werc/ - - -Version Numbering and Branching Rules -------------------------------------- - -There is no such thing! Originally a convention similar to that of the Linux kernel was used, but it is easier to do incremental work on a single branch. - -For radical or experimental changes the `werc-dev` branch might be used, but at the moment it is outdated. - -Bug reports, feature requests, bug fixes and other patches are all very welcome, just send them to the [werc9](http://groups.google.com/group/werc9) mailing list. - - -See Also --------- - -* The [Roadmap](roadmap). -* [TODO](todo) list. diff --git a/sites/werc.cat-v.org/development/roadmap.md b/sites/werc.cat-v.org/development/roadmap.md @@ -1,62 +0,0 @@ -Development Roadmap -=================== - -The versioning scheme is a mess, originally even minor version numbers were -supposed to be stable and odd ones development branches, but turns out that for -the most part it is easier to do incremental development instead of keeping -'dev' and 'stable' branches. - -A development branch might be added in the future if the changes are radical -enough and break backwards compatibility in some important way. For this the -deprecated and currently outdated `werc-dev` mercurial repo will be used. - - -Werc 1.5.x ----------- - -Planed major changes in 1.5 - -* Include required p9p binaries in standard distribution (or with some easy to deploy packaging). -* New/rewritten css layout, perhaps using fluid960gs? -* File upload support [*Code contributed by maht, needs integration*] -* OpenID support [*Code contributed by maht, also needs integration*] -* More complete test suite. - - -Werc 1.4.x, current stable branch ---------------------------------- - -* Mostly bugfixes, documentation work, and minor improvements. - - -Werc 1.2.x, previous stable branch ----------------------------------- - -* Only security fixes. - - -Werc 1.1.x dev branch ---------------------- - -* Convert all templates and pages to HTML 5. [*Done*] -* Include new markdown implementation in pure awk by yuyis.[*Done*] -* Native Plan 9 httpd works out of the box. [*Mostly done*] -* Support for Google's Pubsubhubbub. [*Experimental implementation already done*] -* Include test suite/site (also to be hosted at http://tst.cat-v.org) [*In Progress*] - - -Werc 1.0.x ----------- - -* Abandoned, please upgrade. - - ------------------------------------------------------ - -Werc 2.0 Plans --------------- - -* Big redesigns / rewrites. -* Any non-backwards compatible changes. -* Bring some sanity to the function/config-variable naming insanity. -* Nothing else planned yet. diff --git a/sites/werc.cat-v.org/development/todo.md b/sites/werc.cat-v.org/development/todo.md @@ -1,88 +0,0 @@ -Plans and Ideas for the Future -============================== - -This page lists various assorted ideas and features that have been proposed at -some point or another, nothing (except fixing the listed bugs) is assured to be -implemented, many things here might turn out to be bad ideas. - -Features --------- - -* Review ideas from: http://www.w3.org/TR/chips/ and http://www.w3.org/Provider/Style/URI and see if we can do better. -* Canonize and redirect all requests, we already do this for things like missing or trailing /, should do the same for /. and /./, etc. Deleting trailing . and , should make pasted urls in emails work as links (**Mostly done in RC1**) -* Blog: - * Comment threading. - * Some form of pagination (taking advantage of history browsing.) (**Partially done**) -* Sitemaps: - * Index pages should be used for description of directories. - * Cache web sitemap generation. (**Done in RC0**) -* Layout improvements: - * Need to find a way to rig the order of items in the sidebar. - * Right sidebar. - * Top+left/right nav vars (breadcrumbs at the top, current dir listing on the side) - * Make it easier to disable all sidebars and headers/footers, eg., for full screen mode. - * More testing and optimizations for mobile browsers, eg., http://www.operamini.com/demo/ Left sidebar had some minor issues in cellphones at some point. -* Better page titles (include whole path hierarchy?) (**Partially done, is it good enough now?**) -* Allow utf-8 characters in path elements (need to make sure this is safe, and not sure how useful it will be) -* General code: - * Write a regression test suite. (*Started*) - * Replace all references to non p9p/p9 programs (*Done?*) - * Document better the 'API' for sub-apps, both a set of environment vars apps can rely on (and in some cases set) and functions they can call (WIP). -* Better generation of descriptive HTML META tags, eg.,: {META name="description" content="This is the Google Summer of Code blog for Plan9 and Inferno projects."} {META name="keywords" content="google, summer of code, inferno, plan9, programming"} -* Should add werc to certain wikipedia lists: - * `http://en.wikipedia.org/wiki/List_of_content_management_systems` - * `http://en.wikipedia.org/wiki/Comparison_of_wiki_software` -* Include txt2tags as builtin alternative to markdown. -* Spam protection: - * Mathematic pseudo-CAPTCHA ala WP's 'Math Comment Spam Protection Plugin'. - * kfx (via cinap) suggests you just put a hidden text input box (or textarea?), "Dont write in this input box: [ ..... ]", if the bots fill it out ignore the post - - - -Future Plans and Blue Sky --------------------------- - -* Wanted [apps](/apps/): - * Tagging, eg., append to _werc/tags - * Related links sidebar generation. - * [Bug/issue tracking app](/apps/gregor/). - * Hg/git repository browser. - * Implement AtomPub. - -* Further modularization and extensibility (meta-templates) (Is the new app framework enough for this?) -* A way to wrap external cgi applications (eg., existing hg/git browser) -* A way to generate static sites (ie., use werc as an offline templating system) -* [9P](http://9p.cat-v.org) interface. -* New (simplified) markdown implementation, ideally in C or awk (maybe smu/libsmu by gottox?), yiyus great md2html.awk is a great start! - * Simplified - * Tables - * Images - * Autogenerated anchors/navigation boxes - * No inline html - -Similar frameworks to be investigated and mined for good ideas to steal: - - * TinyTim: http://www.reddit.com/r/programming/duplicates/dbaee/ - * nanoblogger: http://nanoblogger.sourceforge.net/ - - -Known Bugs ----------- - -* It seems that certain chars are not propely encoded in cookies, possibly broken chars: :&%[+ Fix should go in cgilib.rc^set_cookie (Have to figure out the proper way to scape cookie strings first) -* If a dir under apps/ doesn't contain an app.rc file, werc fails to start. A possible fix would be to replace $werc_apps default with `apps/*/app.rc` instead of `apps/*/`, this would be backwards incompatible, but I doubt anyone uses that option. -* Links in Blagh feeds become confused if markdown 'references' are used, markdown references suck, but I guess we need to address this somehow... -* Somewhat similarly to the abouve, relative urls in imgs, links, etc. can easily break when used in Blagh posts, so it is not all markdown's fault. -* .md files of the following form, without a new line after the last = seem to cause problems in some setups: - - Foo Bar - ======= - - - -Fixed or WFM Bugs ------------------ - -* Sitemap can handle $dirfilter inconsistently from other places (**fixed**). -* Finding directories that are inaccessible (-rx) can generate an infinite loop (**Works for me? Fixed with new menu code?**) -* Some cat-v.org bits still left over here and there, should make them configurable (1.0 blocker) (**fixed**?) diff --git a/sites/werc.cat-v.org/docs/_werc/config b/sites/werc.cat-v.org/docs/_werc/config @@ -1 +0,0 @@ -conf_perm_redirect _ - diff --git a/sites/werc.cat-v.org/docs/config-options.md b/sites/werc.cat-v.org/docs/config-options.md @@ -1,68 +0,0 @@ -Werc Configuration Options -========================== - -You can also find a description of some basic config options in the `etc/initrc` file itself. - -General Setup Options --------------------- - -* `formatter` - Command to use for document formatting (usually some form of markdown), should be able to take input both from file names passed as arguments or from stdin if no file names are provided. By default: `formatter=(fltr_cache markdown.pl)` - - -Titles and Metadata -------------------- - -Variables: - -* Page title: - * siteTitle - * siteSubTitle - -* Html header meta tags: - * meta_description - `<meta name="description" ...` - * meta_keywords - `<meta name="keywords" ...` - * extraHeaders - Raw extra html headers, the content of this var will be inserted inside the `<head>` tag.. - - -Sidebar and Navigation ----------------------- - -Variables: - -* sideBarNavTitle - -Functions: - -* `conf_hide_paths [path_patterns ...]` - Hide the given patterns from navigation menu, sitemap and dir listing (do *not* depend on this for security!). - -HTTP Control ------------- - -Variables: - -* extraHttpHeaders - Raw HTTP headers to be added to response. - -Functions: - -* `conf_perm_redirect [pattern] destination` - If pattern is provided, match it against the requested url, and replace the match with `destination`; ie., *s/pattern/destination/. - - -Access Control and Permissions ------------------------------- - -The permissions system is very flexible, for example to only allow access to members of the group 'editors' you can do something like: - - switch ($req_path) { - case /_users/login - case /pub/* - case /robots.txt - case * - if(! check_user editors) - perm_redirect /_users/login - } - - -To automatically redirect users without permission to the login page if they are not members of the group 'editors'. - -See also [the documentation on user and group management](user_management). - diff --git a/sites/werc.cat-v.org/docs/css-style.md b/sites/werc.cat-v.org/docs/css-style.md @@ -1,18 +0,0 @@ -Custom CSS Stylesheets -===================== - -If you create a file under your site's dir at _werc/pub/style.css it will be included automatically after the standard werc stylesheet. - -You can copy pub/style/style.css and customize it, or you can take a simpler file and just change the main color theme. - -Here is an example of how to set the main werc colors: - - - body { background-color: #FFFFF7; } - .midHeader { background-color: #FFFFE9; } - #side-bar { background-color: #EFFFEF; } - #side-bar a { color: black; } - #side-bar a:hover { - color: white!important; - background-color: #428a42; - } diff --git a/sites/werc.cat-v.org/docs/dir-listings.md b/sites/werc.cat-v.org/docs/dir-listings.md @@ -1,29 +0,0 @@ -Autogenerated Directory Listings -================================ - -If a directory has no `index.md`, `index.html` or `index.txt` and has no other -*main handler* set up by a [werc app](/apps/), the default directory listing -handler is used. - -The default directory handler simply displays the path to the directory, and a -list of links to all files and dirs located at this path. - - -Header and footer ------------------ - -If a `_header.md` or `_footer.md` files are found in the directory, their -contents will be displayed in the corresponding sections before and after -the directory contents. - - -Tuning the item's order ------------------------- - -You can set the `dir_listing_ls_opts` config variable in the dir's corresponding _werc/config to change the way items will be ordered. - -For example to list items in reverse chronological order simply add: - - dir_listing_ls_opts=( -t ) - -The options taken are [the standard Plan 9 ls(1) flags](http://man.cat-v.org/plan_9/1/ls). diff --git a/sites/werc.cat-v.org/docs/rc-template-lang.md b/sites/werc.cat-v.org/docs/rc-template-lang.md @@ -1,56 +0,0 @@ -The Rc Template Language -======================== - -Implemented by Kris, thanks! - -Basic syntax: - -* Lines starting with % are executed as rc commands, the resulting output is inserted in the document. -* use %{ and %} to delimit multi line sections of rc code (note the lack of space between % and { or }! -* To 'inline' the value of an environment variable use `%($my_var%)` - -That is basically it! - -For further documentation on rc see: - -* [The rc(1) man page from Plan 9](http://man.cat-v.org/plan_9/1/rc). -* [The rc shell paper by Tom Duff](http://rc.cat-v.org). - - -Examples --------- - -Loops - - <ul> - % for(i in a b c) { - % echo '<li>'$i'</li>' - % } - </uL> - -Can also be writen as: - - <ul> - %{ - for(i in a b c) { - echo '<li>'$i'</li>' - } - %} - </uL> - -and is equivalent to: - - <ul> - % for(i in a b c) { - <li>%($i%)</li> - % } - </uL> - -All three code examples result in this output: - - <ul> - <li>a</li> - <li>b</li> - <li>c</li> - </ul> - diff --git a/sites/werc.cat-v.org/docs/site-customization.md b/sites/werc.cat-v.org/docs/site-customization.md @@ -1,53 +0,0 @@ -Site Customization -================== - -To change any of the default templates or include files found in /lib/ simply copy them from /lib/ to your site's _werc/lib/ and edit at will. - -To change any of the templates found in /tpl/ (e.g. sitemap.tpl), copy the file to your site's root (e.g. /sites/foo.bar.com/sitemap.tpl) and then edit. - -File Types ----------- - -* '.tpl' files are rc [template files](rc_template_lang). -* '.inc' are text files that are inserted 'as is' without any extra processing. - -Site Groups ------------ - -Site configuration and customization and be 'grouped' to allow a shared set of templates among a specific group of sites (useful for sets of sub-domains for example). - -Simply set 'masterSite' configuration variable to the name of the site you want to 'inherit' templates, style and configuration from. - -For example, if we have two sites bar.com and foo.bar.com, and in sites/foo.bar.com/_werc/conf we add: - - masterSite=bar.com - -When a template (eg., 404.tpl) is requested it will be looked up first in /sites/foo.bar.com/_werc/lib/404.tpl, if that fails then in /sites/bar.com/_werc/lib/, and if that is missing too, the default /lib/404.tpl is used. - -The same applies to .inc files. - - -List of Template and Included Files ------------------------------------ - -Here is a list of the most commonly used templates and include files with their corresponding descriptions. - -Include: - -* top_bar.inc: The thin header at the top of every page, usually contains static links to other related sites or anything else you like. -* footer.inc: Similar but at the bottom of every page, by default includes a link to the user login page. -* headers.inc: Raw html headers to be included inside <head> tag. - -Templates: - -* default_master.tpl: This is the main template, which calls all the sidebar and other handlers and applications, usually you won't need to edit it unless you want to make changes to the layout or similar dramatic changes. -* sitemap.tpl: Template for the sitemap page. -* 404.tpl: Template for 'File Not Found' pages. - - -See also --------- - -* [CSS style sheets customization](css_style). - - diff --git a/sites/werc.cat-v.org/docs/user-management.md b/sites/werc.cat-v.org/docs/user-management.md @@ -1,36 +0,0 @@ -User and Group Management -========================= - -User account and group membership information are stored under `etc/users/`. - -A user account consists of a directory under `etc/users/` that contains files with that users account information, the only required file is `password` containing a password for the user. For example: - - % ls etc/users/ - eekee uriel yosyp - % cat etc/users/uriel/password - mypass - -Users and groups share the same namespace, you can create a group the same way you create a user but instead of a 'password' file adding a 'members' file containing the names of the group members, one per line. - -A 'user-group' directory can contain both a password and members file, in which case it will act concurrently as a user and as a group. - -The group 'admin' is 'built-in' and any members in that group will have admin privileges for most werc apps by default. - -Example -------- - -To create a user called [glenda](http://glenda.cat-v.org) that is a member of the group `rabbits` you can do: - - % mkdir etc/users/glenda/ - % echo carrot > etc/users/glenda/password - % mkdir -p etc/users/rabbits - % echo glenda >> etc/users/rabbits/members - -Utils ------ - -The script at bin/aux/addwuser.rc allows you to even more trivially add users. - - addwuser.rc user_name user_pass [groups ...] - - diff --git a/sites/werc.cat-v.org/docs/web-server-setup/_header.md b/sites/werc.cat-v.org/docs/web-server-setup/_header.md @@ -1,16 +0,0 @@ -Setting Up Your HTTP Server to Run Werc -======================================= - - -Werc should work with any web server that supports the CGI interface, and a few -that don't. Here are collected instructions and sample configurations for some -of the most popular HTTP servers that people has used with werc. - -In general setup consists of mapping all paths for a virtual host to the -werc.rc script, usually in practice this means that the `document root` (or -similar concept) for a virtual host is mapped to -`/path/to/werc/sites/domain.name.com/`, and if no static file matches the -request, control is handed to werc.rc, this allows the HTTP server to handle -static files and werc to handle everything else (note that such a setup will -expose your `_werc/config` files, which usually should not be a security -issue). diff --git a/sites/werc.cat-v.org/docs/web-server-setup/apache.md b/sites/werc.cat-v.org/docs/web-server-setup/apache.md @@ -1,93 +0,0 @@ -Setup werc with Apache -====================== - -Note: Apache 2.x configuration should be similar to 1.3.x, but Apache 2.x is not recommended due to unwindy complexity, please use a saner web server. - -Apache 1.3.x: minimalist configuration -====================================== - -No virtual hosts and let werc handle static files. - - RewriteEngine On - ServerName test.cat-v.org - AddHandler cgi-script .rc - - <Directory /var/www/werc/bin> - Options ExecCGI - </Directory> - <IfModule mod_dir.c> - DirectoryIndex /werc.rc - </IfModule> - - RewriteRule /werc.rc /var/www/werc/bin/werc.rc - DocumentRoot /var/www/werc/bin/ - ErrorDocument 404 /werc.rc - - -Apache 1.3.x: standard configuration -==================================== - -This lets apache handle static files. - - <VirtualHost *> - - RewriteEngine On - ServerName test.cat-v.org - AddHandler cgi-script .rc - - <Directory /var/www/werc/bin> - Options ExecCGI - </Directory> - <IfModule mod_dir.c> - DirectoryIndex /werc.rc - </IfModule> - - RewriteRule (.*) /var/www/werc/sites/%{HTTP_HOST}/$1 - - RewriteCond %{REQUEST_FILENAME} !-f - RewriteRule .* /var/www/werc/bin/werc.rc - - RewriteRule /werc.rc /var/www/werc/bin/werc.rc - DocumentRoot /var/www/werc/bin/ - ErrorDocument 404 /werc.rc - - </VirtualHost> - - -Apache 1.3.x: advanced configuration -==================================== - - - <VirtualHost *> - - RewriteEngine On - ServerName cat-v.org - ServerAlias www.cat-v.org harmful.cat-v.org 9p.cat-v.org gsoc.cat-v.org doc.cat-v.org uriel.cat-v.org www.binarydream.org ninetimes.cat-v.org *.cat-v.org - AddHandler cgi-script .rc - AddHandler cgi-script .cgi - <Directory /home/uriel/cat-v.org/bin> - Options ExecCGI - </Directory> - <IfModule mod_dir.c> - DirectoryIndex /werc.rc - </IfModule> - - RewriteRule ^/hg/(.*) /home/uriel/cat-v.org/bin/hgwebdir.cgi/$1 [L] - - RewriteRule /pub/style/style.css /home/uriel/cat-v.org/pub/style/style.css [L] - RewriteRule /pub/ /home/uriel/cat-v.org/pub/ [L] - RewriteRule /favicon.ico /home/uriel/cat-v.org/pub/default_favicon.ico [L] - - - RewriteRule (.*) /home/uriel/cat-v.org/sites/%{HTTP_HOST}/$1 - - RewriteCond %{REQUEST_FILENAME} !-f - RewriteRule .* /home/uriel/cat-v.org/bin/werc.rc - - RewriteRule /werc.rc /home/uriel/cat-v.org/bin/werc.rc - DocumentRoot /home/uriel/cat-v.org/bin/ - ErrorDocument 404 /werc.rc - - </VirtualHost> - - diff --git a/sites/werc.cat-v.org/docs/web-server-setup/cherokee.md b/sites/werc.cat-v.org/docs/web-server-setup/cherokee.md @@ -1,31 +0,0 @@ -Configuring werc with Cherokee -============================== - -Contributed by sqweek, thanks! - -Cherokee Version 0.7.1 ----------------------- - - vserver!default!rule!600!only_secure = 0 - vserver!default!rule!600!handler = cgi - vserver!default!rule!600!handler!error_handler = 1 - vserver!default!rule!600!handler!check_file = 1 - vserver!default!rule!600!handler!script_alias = - /usr/local/werc/bin/werc.rc - vserver!default!rule!600!handler!pass_req_headers = 0 - vserver!default!rule!600!match = directory - vserver!default!rule!600!match!directory = /code - vserver!default!rule!600!match!final = 1 - - -Cherokee Version 0.5.3 ----------------------- - - Directory /code { - Handler cgi { - Scriptalias /usr/local/werc/bin/werc.rc - } - } - - -Isn't progress wonderful? diff --git a/sites/werc.cat-v.org/docs/web-server-setup/hiawatha.md b/sites/werc.cat-v.org/docs/web-server-setup/hiawatha.md @@ -1,16 +0,0 @@ -Hiawatha Web Server Configuration ---------------------------------- - -Contributed by sqweek, thanks! - -This are the relevant bits: - - CGIhandler = /usr/local/plan9/bin/rc:rc - ExecuteCGI = yes - RewriteURL = werc - UrlRewrite { - RewriteID = werc - Match ^(/code|/index|/contact|/clique).* Rewrite /werc.rc - Match ^/$ Rewrite /werc.rc - } - diff --git a/sites/werc.cat-v.org/docs/web-server-setup/lighttpd.md b/sites/werc.cat-v.org/docs/web-server-setup/lighttpd.md @@ -1,44 +0,0 @@ -Setup werc with lighttpd -======================== - -You will need to enable to the following modules: `mod_cgi`, `mod_alias` and `mod_rewrite` (for non-minimal configurations). - -You can also find `mod_setenv` useful to change werc's environment ($PATH in perticular) - -Minimal setup -------------- -This is the most minimal setup, for a single domain, and lets werc handle static files. - - $HTTP["host"] =~ "^test\.cat-v\.org$" { - index-file.names = ( ) - server.error-handler-404 = "/werc.rc" - alias.url += ( "/werc.rc" => "/var/www/cat-v.org/bin/werc.rc" ) # Here use the path to werc.rc in your system. - cgi.assign += ( ".rc" => "") - server.dir-listing = "disable" - } - -Advanced setup --------------- - -A more ellaborate setup, using virtual hosts to handle multiple domains, and -alias to let lighttpd handle static files. Also show how to add external cgi's -to the setup, in this case Mercurial's web interface. - - $HTTP["host"] =~ "^((harmful|9p|gsoc|doc|uriel|src|repo|www|)(\.|)cat-v\.org|(www\.)?binarydream.org|)$" { - - index-file.names = ( ) - evhost.path-pattern = "/var/www/cat-v.org/sites/%3.%0/" - server.error-handler-404 = "/werc.rc" - - alias.url += ( "/pub/" => "/var/www/cat-v.org/pub/" ) - alias.url += ( "/favicon.ico" => "/var/www/cat-v.org/pub/default_favicon.ico" ) - alias.url += ( "/doc/" => "/var/www/cat-v.org/sites/doc.cat-v.org/" ) - alias.url += ( "/werc.rc" => "/var/www/cat-v.org/bin/werc.rc" ) - alias.url += ( "/debug.rc" => "/var/www/cat-v.org/bin/debug.rc" ) - cgi.assign += ( ".rc" => "") - server.dir-listing = "disable" - - cgi.assign += ( ".cgi" => "") - url.rewrite-once = ( "/hg/(.*)" => "/hg/hgwebdir.cgi/$1" ) - alias.url += ( "/hg/" => "/var/www/cat-v.org/bin/" ) - } diff --git a/sites/werc.cat-v.org/docs/web-server-setup/nginx.md b/sites/werc.cat-v.org/docs/web-server-setup/nginx.md @@ -1,96 +0,0 @@ -Setup werc with NGINX -===================== - -You probably will want to to use fcgiwrap, called from spawn-fcgi or similar. - -Here is an extremely basic nginx configuration, with this configuration static files will be handled by werc and not nginx, this is clearly dumb, but works: - - worker_processes 1; - - #error_log logs/error.log; - #error_log logs/error.log notice; - error_log logs/error.log info; - - pid logs/nginx.pid; - - events { - worker_connections 1024; - } - - - http { - include mime.types; - default_type application/octet-stream; - - #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - # '$status $body_bytes_sent "$http_referer" ' - # '"$http_user_agent" "$http_x_forwarded_for"'; - - #access_log logs/access.log main; - - sendfile on; - #tcp_nopush on; - - #keepalive_timeout 0; - keepalive_timeout 65; - - #gzip on; - - server { - listen 80; - server_name test.cat-v.org; # Replace with your domain name. - - #charset utf-8; - - #access_log logs/host.access.log main; - - location / { - - # FastCGI params, usually stored in fastcgi_params - # and imported with a command like the following: - #include fastcgi_params; - - # Typical contents of fastcgi_params (inlined here): - fastcgi_pass localhost:9000; - - fastcgi_param QUERY_STRING $query_string; - fastcgi_param REQUEST_METHOD $request_method; - fastcgi_param CONTENT_TYPE $content_type; - fastcgi_param CONTENT_LENGTH $content_length; - - #fastcgi_param SCRIPT_FILENAME /var/www/werc/bin/werc.rc; - fastcgi_param SCRIPT_NAME /var/www/werc/bin/werc.rc; - #fastcgi_param SCRIPT_NAME $fastcgi_script_name; - - fastcgi_param REQUEST_URI $request_uri; - fastcgi_param DOCUMENT_URI $document_uri; - fastcgi_param DOCUMENT_ROOT $document_root; - fastcgi_param SERVER_PROTOCOL $server_protocol; - - fastcgi_param GATEWAY_INTERFACE CGI/1.1; - fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; - - fastcgi_param REMOTE_ADDR $remote_addr; - fastcgi_param REMOTE_PORT $remote_port; - fastcgi_param SERVER_ADDR $server_addr; - fastcgi_param SERVER_PORT $server_port; - fastcgi_param SERVER_NAME $server_name; - fastcgi_param REMOTE_USER $remote_user; - - #root /var/www/werc/sites/$server_addr; # XXX This doesn't work, not sure why :( - root /; - #index index.html index.htm; - } - } - } - - -Then you can use spawn-fcgi or similar to get wrapcgi going: - - spawn-fcgi -a 127.0.0.1 -p 9000 -f /home/uriel/dvl/ext/fcgiwrap/fcgiwrap # Use the path to your fcgiwrap binary here - - -Other Setups ------------- - -More elaborate setups with direct handling of static files, caching, and multiple fcgi/cgi handlers should be easy, if you have any please post them to the werc9 mailing list. diff --git a/sites/werc.cat-v.org/docs/web-server-setup/nhttpd.md b/sites/werc.cat-v.org/docs/web-server-setup/nhttpd.md @@ -1,60 +0,0 @@ -Nhttpd/Nostromo Web Server Configuration for Werc -================================================== - -Contributed by nsz, thanks! - -The last two sections are relevant: aliases (to make non-content site material, -like css, available) and virtual hosts (the document root is set to `werc.rc` -so it will handle every request). - - # MAIN [MANDATORY] - - servername main.host.com - serveradmin admin[at]mail.com - serverroot /var/nostromo - servermimes conf/mimes - logpid logs/nhttpd.pid - logaccess logs/access_log - docroot /var/nostromo/htdocs - docindex index.html - - # SETUID [RECOMMENDED] - - user nhttpd - - # BASIC AUTHENTICATION [OPTIONAL] - #... - - # SSL [OPTIONAL] - #... - - # CUSTOM RESPONSES [OPTIONAL] - #... - - # HOMEDIRS [OPTIONAL] - #... - - # ALIASES [OPTIONAL] - - /pub /path/to/werc/pub - # The following line doesn't work because nhttpd doesn't support file aliases yet. - #/favicon.ico /path/to/werc/pub/default_favicon.ico - - # VIRTUAL HOSTS [OPTIONAL] - - vhost1.com /path/to/werc/bin/werc.rc - vhost2.com /path/to/werc/bin/werc.rc - #... - -To use werc on `main.host.com` as well just set `docroot` to `/path/to/werc/bin/werc.rc` -and set `docindex` to empty string. - -There was a bug in nhttpd <=1.9, it did not set `SERVER_NAME` properly (left it `main.host.com`). -To solve this problem just add a - - SERVER_NAME=$HTTP_HOST - -line somewhere at the top of `werc.rc`. - - - diff --git a/sites/werc.cat-v.org/docs/web-server-setup/plan-9-httpd.md b/sites/werc.cat-v.org/docs/web-server-setup/plan-9-httpd.md @@ -1,53 +0,0 @@ -Setup werc with Plan 9's httpd -============================== - - -There are two main options, you can use Russ Cox's magic to cgi translator -(found in his contrib dir as cgi.c), or you can use the following script which -while simpler, it also lacks some features at the moment. - -Thanks to soul9 for the original idea of wrapping werc in a shell script that -would setup a cgi-like environment! - - - #!/bin/rc - - SERVER_NAME=$2 - REQUEST_URI=`{echo $*(15)} - REQUEST_URI=$REQUEST_URI(2) - REQUEST_URI=/ - REQUEST_METHOD=$*(16) - PLAN9=/ - - - echo 'HTTP/1.0 200 Ok - Connection: close - Server: werc/9.9.9' # This is whatever you like - - - cd /usr/web/bin/ - rfork - /bin/rc < ./werc.rc >[2]/usr/glenda/tmp/w/log # Use whatever location you like to log stderr, but make sure it is writable by none. - -Call this script werc-wrap, and put it in /rc/bin/ip/httpd/ - -Then in your /sys/lib/httpd.rewrite add a line like: - - /w @/magic/werc-wrap - -And this will run werc for all stuff under /w. Note that apparently httpd is -incapable of internally remapping the root directory, so until a solution is -found for this, you will have to keep your site in a sub-directory of the web -server root. - -In your /lib/namespace.httpd you probably will want to add something along the -following lines to bind the werc directory into the httpd's namespace: - - bind -b /usr/glenda/src/werc/ /usr/web/ - bind /usr/glenda/src/werc/bin/ /usr/web/magic/ - - -**Notes**: This is experimental and work in progress, there are a couple of issues -with the werc code itself that might need fixing, in particular you will need -to replace the '%($"extraHeaders%)' in lib/headers.tpl with '% echo -$"extraHeaders' no clue why. diff --git a/sites/werc.cat-v.org/index.md b/sites/werc.cat-v.org/index.md @@ -1,104 +0,0 @@ -werc - A sane web anti-framework -================================ - -Werc is a minimalist web anti-framework built following the [Unix](http://doc.cat-v.org/unix/) and [Plan 9](http://plan9.cat-v.org) -*tool philosophy* of software design. - -Werc avoids the pain of managing collections of websites and developing web -applications. - -* Database free, uses files and directories instead. -* Written using [the rc shell](http://rc.cat-v.org), leveraging the standard Unix/Plan 9 command toolkit. -* Minimize tedious work: eg., no need to ever write HTML, use markdown (or any other format) instead. -* Very minimalist yet extensible codebase: highly functional core is 150 lines, with extra functionality in modular [apps](/apps/). - - -Features --------- - -Here are some of the features provided by werc: - -* Good integration with pre-existing content, you can add HTML or plain text files and they will be seamlessly integrated with the rest of the site. -* You can use your favorite tools (text editor, shell, file manager, etc) to edit, manipulate and manage data stored in werc. -* Designed to manage any number of 'virtual' domains that share a common style and layout from a single werc installation. -* Configuration and customization can be at at any level: global, per-domain-group, domain-wide, directory sub-tree, and single file. -* Can trivially run multiple (customized) versions of werc side by side. -* Very simple and flexible user management and permissions system. -* Applications can be easily combined: eg., add comments to your blog or wiki by enabling the 'bridge' app; or by enabling the 'diridir' wiki convert any document tree into a wiki. -* Can easily write werc 'apps' and extensions in *any* language! (But of course, rc is recommended). - - -Install Requirements --------------------- - -All you need is some Plan 9 commands (cat, grep, sed, rc, etc.), and an HTTP -server with CGI support. - -Werc runs on any Unix-like system where [Plan 9 from User Space](http://plan9.us) -is available (this includes Linux, *BSD, OS X and Solaris), and on Plan 9. - -If you use Debian you can install the `9base` package that will provide all the -required commands (but at the moment you need to install the version in *sid*, -older versions in stable lack some of the required programs) - -Werc can use any HTTP server that can handle CGI, and has been tested with at -least Apache, Lighttpd, Cherokee, nhttpd, Hiawatha, and others. - -Werc uses markdown by default (and the standard Perl markdown is included with -the distribution), to format documents, but any other formatting system can be -used. - - -Source ------- - -To get a copy of the latest stable code using mercurial, do: - - hg clone http://hg.cat-v.org/werc/ - -You can also [browse the online repository](http://gsoc.cat-v.org/hg/werc/). - -The latest development branch is located at http://gsoc.cat-v.org/hg/werc-dev/ - - -Contact -------- - -For questions, suggestions, bugrepports and contributing patches you can join -the [werc9 mailinglist](http://groups.google.com/group/werc9). - -On irc, join [#cat-v](irc://irc.freenode.org/cat-v) on irc.freenode.org - - -Links ------ - -* [werc project at freshmeat](http://freshmeat.net/projects/werc/) - You can get new release notifications there. -* [werc project at ohloh](https://www.ohloh.net/p/werc/) - - -License -------- - -Public domain, [because so called 'intellectual property' is an -oxymoron](http://harmful.cat-v.org/economics/intellectual_property/). - -Alternatively if your prefer it or your country's brain dead copyright law -doesn't recognize the public domain werc is made available under the terms of -the MIT and ISC licenses. - - -Credits -------- - -Thanks to Kris Maglione (aka JG) for implementing rss feeds, for writing the -awk rc-templating system, and other help and inspiration (some parts of the -code were based on JG's diri wiki). - -Thanks to Mechiel (aka oksel) for the md_cache script. - -Thanks Garbeam (aka arg) for writing the original diri code and showing that -writing complex web apps in rc was feasible. - -And thanks to everyone else whom I have forgotten and that has provided fixes -and feedback. diff --git a/sites/werc.cat-v.org/testimonials.md b/sites/werc.cat-v.org/testimonials.md @@ -1,8 +0,0 @@ -Comments from Werc Fans -======================= - -*When people ask me what I look for in a woman, I'm going to say, "werc-like qualities".* -- shardz - -*Okay, werc gets my official Mark of Sweetness. This is really damn nice.* -- Athas - -*Thanks to [Uriel](http://uriel.cat-v.org) and co. for providing the wonderful werc framework.* -- sleepydog, maintainer of Xpilot-AI [http://www.reddit.com/r/programming/comments/9m2nl/xpilotai_development_of_autonomous_agents_in/c0dch6s] diff --git a/sites/werc.cat-v.org/wiki/_werc/config b/sites/werc.cat-v.org/wiki/_werc/config @@ -1 +0,0 @@ -conf_enable_wiki diff --git a/tpl/404.tpl b/tpl/404.tpl @@ -0,0 +1,3 @@ +<h1>The requested document at '<i>%($base_url$"req_path%)</i>' doesn't exist</h1> + +<h4>Or take a look at the <a href="/sitemap">sitemap</a>.</h4> diff --git a/tpl/_debug.tpl b/tpl/_debug.tpl @@ -1,29 +0,0 @@ -% if(! ~ $#debug_shell 0) { -<form method="POST" name="prompt"> -<input size="80" type="text" name="command" value="%($"post_arg_command%)"> -<input type="submit" Value="Run"> -</form> -<script language="javascript"><!-- -document.prompt.command.focus() -//--></script> - -%{ -fn evl { - # Buffering is probably messing this up: - #rc -c 'flag x +;{'^$post_arg_command'} |[2] awk ''{print ">> "$0}''' - rc -c 'flag s +; flag x +;'^$post_arg_command -} - if(! ~ $#post_arg_command 0 && ! ~ $#post_arg_command '') { - echo '<hr><pre>' - evl | escape_html |[2] awk '{print "<b>"$0"</b>"}' - echo '</pre>' - } -%} -% } - -<hr><pre> -% env | escape_html -</pre><hr> - -% umask - diff --git a/tpl/_users/login.tpl b/tpl/_users/login.tpl @@ -1,18 +0,0 @@ -<h1>User login</h1> -<br /> -% if(check_user) { - You are logged in as: <b>%($logged_user%)</b> -% } -% if not { -% if (~ $REQUEST_METHOD POST) -% echo '<div class="notify_errors">Login failed!</div>' -<form method="POST" action="" style="text-align: right; float: left;"> -<fieldset> - <label>User name: <input type="text" name="user_name" value="%($"post_arg_user_name%)"/></label><br> - <label>User password: <input type="password" name="user_password"></label><br> - <input name="s" type="submit" value="Login"> -</fieldset> -</form> -% } - -<br style="clear:left"> diff --git a/tpl/master.tpl b/tpl/master.tpl @@ -0,0 +1,70 @@ +<!doctype html> +<html> +<head> + <title>%($pageTitle%)</title> +% env > /tmp/x.txt +% style = `{get_cookie style} +% if(~ $"style 1) { + <link rel="stylesheet" type="text/css" href="/pub/style1.css"> +% } +% if not { + <link rel="stylesheet" type="text/css" href="/pub/style.css"> +% } + <meta charset="utf-8"> +</head> +<body> + <div id="menu"> + <a href="http://suckless.org">home</a> | + <a href="http://hg.suckless.org">code</a> | + <a href="http://dl.suckless.org">download</a> | + <a href="http://man.suckless.org">man</a> | + <a href="http://dwm.suckless.org">dwm</a> | + <a href="http://libs.suckless.org">libs</a> | + <a href="http://st.suckless.org">st</a> | + <a href="http://sta.li">stali</a> | + <a href="http://surf.suckless.org">surf</a> | + <a href="http://tools.suckless.org">tools</a> | + <a href="http://wmi.suckless.org">wmi</a> + </div> + <div id="header"> +% if(! ~ $#siteImage 0) { + <a href="/"><img src="%($"siteImage%)" alt="%($"siteTitle%)"/> <span id="headerSubTitle">%($"siteSubTitle%)</span></a> +% } +% if not { + <a href="/">%($"siteTitle%) <span id="headerSubTitle">%($"siteSubTitle%)</span></a> +% } + </div> + + <div id="content"> +% if(! ~ $#handlers_bar_left 0) { + <div id="nav"> +% for(h in $handlers_bar_left) { +% run_handler $$h +% } + </div> +% } + + <div id="ads"> + </div> + <div id="main"> + +% run_handlers $handlers_body_head + +% run_handler $handler_body_main + +% run_handlers $handlers_body_foot + + </div> + + </div> + + <div id="footer"> + <div class="left"> + <a href="http://werc.cat-v.org/">Powered by werc</a> + </div> + <div class="right"> + &copy; 2006-2012 suckless.org community + </div> + </div> +</body> +</html> diff --git a/tpl/sitemap.tpl b/tpl/sitemap.tpl @@ -55,9 +55,6 @@ if(test -s $tmpfilex) { cat $tmpfilex rm $tmpfilex & echo '</urlset>' - # TODO Enable automaic search engine update notification. - #hget 'http://google.com/ping?sitemap='^`{url_encode $base_url'/sitemap.gz'} > /dev/null - } | gzip > $sitedir/sitemap.gz & #} > $sitedir/sitemap.xml & }