#!/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: [{&} {&amp;} {^/^/} {</p> <p>} {--} {&#8212;}]
    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&#8217;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> " &#8212; "
            entry/content " &#8212; "
            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