#!/path/to/rebol --cgi
REBOL [
title: "Blosxom"
file: %blosxom.r
purpose: "Simple Blog Mechanics"
author: ["Rael Dornfest" "Christopher Ross-Gill"]
comment: {
Blosxom
Original Author: Rael Dornfest <rael@oreilly.com>
Based on Version: 0+4i
Original Home/Docs/Licensing: http://www.oreillynet.com/~rael/lang/perl/blosxom/
No RSS output here, yet.
}
home: http://www.ross-gill.com/
]
print "content-type: text/html; charset=ISO-8859-1^/^/"
; String Output
entries-out: make string! 1000
emit: func [data][repend entries-out data]
nsp: "^/ " ; I use this for code style
; A simple format function
format-text: func [text /local replacees][
replacees: [{&} {&} {^/^/} {</p> <p>} {--} {—}]
foreach [from to] replacees [replace/all text from to]
replace/all trim/lines text { <p>} {^/ <p>}
]
blosxom: context [
; --- Configurable values -----
; What's my blog's title?
blog-title: "Blosxom"
; What's my blog's description (for outgoing RSS feed)?
description: "Yet another Blosxom blog."
; What's my blog's primary language (for outgoing RSS feed)?
language: "en"
; Where are my blog entries kept?
datadir: %../path/to/blog/
; How many entries should I show on the home page?
num-entries: 20
; Relative URL of this script.
url: %/cgi-bin/blosxom.r
; Convert the path info to a date
path-info: system/options/cgi/path-info
date: either all [
path-info
not empty? path-info
not error? try [to-date next path-info]
][
to-date next path-info
][
now/date
]
; Obtain a list of file entries
files: read datadir
shortdate?: func [date [date!]][date/date]
remove-each file files [
insert file datadir
not all [
equal? %.txt suffix? file
not greater? shortdate? modified? file date
]
]
; Sort and copy newest entries
newest-first: func [a b][(modified? a) > (modified? b)]
files: copy/part sort/compare files :newest-first num-entries
; Extract content from files
entries: copy []
entry: title: content: entry-date: entry-time: none
foreach file files [
entry-date: modified? file
entry-time: entry-date/time
entry-date: entry-date/date
content: read file
entry: copy []
repend entry [
'date entry-date
'time entry-time
'title title: copy/part content content: find content newline
'content (format-text copy next content)
'permalink replace/all lowercase copy title " " "-"
]
append/only entries entry
]
]
; Some date/time functions
date-funcs: context [
set 'weekday? func [date [date!]][pick system/locale/days date/weekday]
set 'month? func [date [date!]][pick system/locale/months date/month]
set 'date-th? func [date [date!]][
switch/default date/day [
1 ["st"] 2 ["nd"] 3 ["rd"]
21 ["st"] 22 ["nd"] 23 ["rd"]
31 ["st"]
]["th"]
]
set 'get-hour func [time [time!]][
switch/default time/hour [
0 ["Midnight"]
12 ["Noon"]
][
rejoin either time/hour < 12 [[time/hour "am"]][[time/hour - 12 "pm"]]
]
]
]
; Template -- Could be external...
doctype: {<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">}
template: {
<% build-tag compose [html xmlns http://www.w3.org/1999/xhtml xml:lang (blosxom/language) lang (blosxom/language)] %>
<head><title><% blosxom/blog-title %></title>
<meta http-equiv="pragma" content="no-cache" /></head>
<body id="blosxom-rebol">
<h2><% blosxom/blog-title %></h2><%
either empty? blosxom/entries [
emit [
nsp <h3> "Too Far Back" </h3>
nsp <p> {Blog didn’t exist back then.} </p>
]
][
date: now/date + 1
foreach entry blosxom/entries [
if not equal? date entry/date [
date: entry/date
emit [
nsp <h3> weekday? date ", " date/day
date-th? date " " month? date </h3>
]
]
emit [
nsp <p> build-tag compose [a id (entry/permalink)] </a> <strong>
get-hour entry/time
</strong> " — "
entry/content " — "
build-tag compose [
a title "Permanent Link" href (join blosxom/url [
"/" date/year "/" month? date
"/" date/day "#" entry/permalink
])
]
"Link" </a> </p>
]
]
]
entries-out
%>
</body>
</html>}
print build-markup join doctype template