Sometimes just linking to resources isn’t enough…
The below list is a semi-complete list of all the “pages” resources on pages.uwwebpub.com. I try to keep the list updated (and am not interested in making it automated), but I’m not quite perfect.
All of the below works are original copyright (C) by Ryan Timmons of the Catalyst Instructor Team. You are free to reproduce or distribute them provided that they are credited with the source’s URL and aren’t distributed for profit.
I searched high and low for a good lightweight platform to publish these content pages. The “lightest weight” thing I could find was Drupal, which is far too heavy for my liking.
…were simple…
Implicit Markup:
I hate HTML. I needed to be able to post content in plaintext. My preferred plaintext formatting is Markdown, but I would have settled for pretty much anything.
Preferably the platform would also provide a facility for readers to download the content in its “un-HTML” form.
Source-Code Highlighting
Since I post mostly code examples and explanations, any publishing platform had to handle source code reasonably well. I would have settled without syntax highlighting if everything else was done well.
It should also be simple to “hide” blocks on the page using JavaScript. Such as
This is a hidden block
Since this isn’t hard to “hack on” to pretty much anything, I didn’t list it in my “formal requirements” initially.
Portability
I don’t want my content stored in a database. Databases are meant to hold a large of amount of relational data. This body of content is not large or relational. The platform must store content in flat files preferrably with as little embedded “meta” info. as possible.
Ease of Editing
I’m an avid user of Macromates’s TextMate for almost all my text
editing, and I hate typing in <textarea> boxes on online forms. It has
to be dead-simple to update existing content, add new pages, and see a
list of all the content pages at once.
I would also like it if I didn’t have to be connected to a remote machine
to make my edits. If (3) were satisfied, I could always simply rsync a
local copy of the content with the remote copy, but even rsync doesn’t
perform a two-way operation meaning that my local machine may be the only
source of edits.
Page-specific Styles and Scripts
Since this content focuses mostly on web publishing technologies including CSS and JavaScript, the platform needs to be able to allow each page to specify its own stylesheet and javascript information while still having a default set of both so there is a consistent (non-terrible) look to all the pages. The defaults should be able to be “turned off,” but that is not a requirement.
…was obvious. Make my own platform!
I should probably surround “platform” with quotes whenever speaking of this setup, though. It’s really just a bunch of other people’s work glued together in a crazy frankenstein script-slash-configuration.
In particular, requests directed to http://pages.uwwebpub.com are handled by
an instance of Apache with mod_php and mod_rewrite. The server’s source
for web documents, called DocumentRoot in Apache lingo, are at, let’s say,
/users/Pages/lib.
The .htaccess file in /users/Pages/lib looks like
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ ./index.php?url=$1 [QSA,L]
So basically, a page request is received by the server and the dispatched to a parser script called index.php (how original, I know). So going to http://pages.uwwebpub.com/page.html gets, in effect, routed to http://pages.uwwebpub.com/index.php?url=page.html.
The parser script takes the requested URL and finds the respective Pages document and grabs its meta data (such as title, last updated date, stylesheets/scripts, etc.). Then depending on the format of the request the parser script then performs various text transformations.
I consider the “format” of the request to be its extension. So if the user requests php_join.html, the parser runs the php_join file through some text-html filters. If the user requests php_join.txt, the parser runs it through some text-text filters.
For the text-html filters, I’m using PHPMarkdownExtra (a PHP
implementation of Markdown, which was originally written in Perl) and then
GeSHi for syntax highlighting with a couple modified syntax files (I
hated the default PHP syntax definition). I had to modify PHPMarkdownExtra
slightly to integrate it with GeSHi (it recognizes the {{lang:xxx}} lines,
shown below, and then hands the block off to GeSHi). Unfortunately the server
still re-parses the files at each request, and GeSHi is slow as heck (although
it does a pretty good job). Ideally the server would parse the base file once
and cache the results, only re-parsing when the source file’s mod-time has
changed, but that’s something for down the road.
The text-html filters are pretty simple. Here is how a local content file looks:
Title: Some Sort of Example Document
Author: Sir Arthur McFinnigan
<css defaults="true">
a:link { color: green; }
</css>
===
# Example Page
This is an example page. This page as its own internal stylesheet making
[links](http://example.org) green.
I can add source code easily in lots of languages such as PHP
{{lang:php}}
<?php
function counter()
{
static $i = 0;
return $i++;
}
or maybe HTML
{{lang:html}}
<table> <tr><td>Foo</td> <td>Bar</td></tr>
<tr><td>Fud</td> <td>Baz</td></tr> </table>
and a "hidden" block:
{hidden}
This is a hidden block. It will be displayed as usual in the plaintext parsed
version, but the HTML version will replace the `{hidden}` lines with `<div
class="showhide">` which are then turned into what you see normally on the
page using jQuery.
{/hidden}
Everything above the tripe-equals sign above is optional. The parser assumes
default css and javascript and will assume no title if one isn't given and
will assume that I (Ryan Timmons) am the author if one is not specified.
And gets parsed as both HTML output (HTML results) and plaintext (in
which mode the parser moves meta-info to the bottom and removes the
{{lang:xxx}} lines) (plaintext results).
The HTML results are displayed in standard HTML/CSS/JavaScript. The CSS styles for this site were influenced heavily by the excellent “Dawn” theme from TextMate. The default JavaScript script includes the excellent jQuery library for taking care of showing/hiding solution blocks.
And then, finally, to get the data between my local computer and the server, I’m using the excellent file-synchronization utility Unison. I have a very simple script setup that I run whenever I want to synchronize my local and remote copies.
And that’s pretty much it. I’m considering posting more of the code to make this all happen, but it’s all just a product of a caffeine-induced coding marathon one Saturday afternoon, so it’s all a bit rough around the edges. If you’re at all interested in the code, let me know at {rtimmons}atsign{u.washington.edu}, and I’d be happy to send you the code.
That is all.
Author: Ryan Timmons
Last Modified: 06 August 2008 15:23:13 PDT
URL: http://uwwebpub.com/