About taglib
The last iteration of this website was written using mod_wsgi, and
consisted of
- a set of page classes (because I’m a creative genius,
the base class is called Page); and
- a tag-generation library (which, for the reason stated
above, I’ve come to think of as
taglib
).
The tag library is
heavily inspired by an internal
library used at my workplace, but owes no code whatsoever to
it—that library is written in PHP (not my favourite language)
and suffers from various problems, chiefly that it’s old,
predating good language support for OOP, and horrendously
complicated (in places) to modify.
Still, I rather liked the idea, so I decided to see what I
could accomplish in that vein with an afternoon’s Python work.
Apparently, I decided that what I could accomplish was worth
keeping, and I use it here and there in this website—mostly
for fun and because it lets me make shorthand tags
(<entry> for
<div class="entry">
being a simple example). Anyone who’s worked there and
looked at it knows that complex_tag is aptly named
indeed…
It can do more useful things, however, like generating elements
on the fly, dynamically populating them (e.g. from a database),
and so forth.
The next section of this page is rather
inane and simply shows a few examples of taglib in
action. There’s also a source listing
for this page. Both of these really refer to the older
version; what you see was rendered by Django and not by
taglib.
Preliminaries
Here’s some tag soup, with some non-ASCII characters thrown
in. It may be unsurprising that a guy named ‘Häggholm’
should build a library that focuses strictly on Unicode
strings… We’ll be parsing this stuff into an
object-oriented structure.
This has to be valid XML, except that no root element is
required.
Strictly speaking, that means it can’t be real
tag soup
.
Here’s a rather differently generated paragraph.
Here’s another one.
Fun with sequences
Let’s have a list! Note that this is filled with a
dict, which is unordered. You may want some kind of
ordered map for this one…
- Trois!
- Deux!
- Un!
Obviously, we can make ’em unordered.
- Towel
- Sub-etha-thingamajig
- Guide
Source listing
# coding=utf8
from __future__ import with_statement
import codecs
from htpage.page import *
from taglib import tags
from page import phPage
class Taglibdemo(phPage):
"""Page class demonstrating how this stuff works."""
@makepage
def main(self):
"""Invoked by the Page class to fill in the contents.
This is an example of the Abstract Method pattern, to give it a name
fancier than its workings.
"""
soup = u"""<h1>taglib demo page</h1>
<entry>
<h2>About taglib</h2>
<p>
This website was written using <tt>mod_wsgi</tt>, and
consists of
<ol>
<li>a set of page classes (because I’m a creative genius,
the base class is called <tt>Page</tt>); and</li>
<li>a tag-generation library (which, for the reason stated
above, I’ve come to think of as
<q><tt>taglib</tt></q>).</li>
</ol>
The tag library is <em>heavily</em> inspired by an internal
library used at my workplace, but owes no code whatsoever to
it—that library is written in PHP (not my favourite language)
and suffers from various problems, chiefly that it’s old,
predating good language support for OOP, and horrendously
complicated (in places) to modify.
</p>
<p>
Still, I rather liked the idea, so I decided to see what I
could accomplish in that vein with an afternoon’s Python work.
Apparently, I decided that what I could accomplish was worth
keeping, and I use it here and there in this website—mostly
for fun and because it lets me make shorthand tags
(<tt><entry></tt> for
<tt><div class="entry"></tt>
being a simple example). Anyone who’s worked there and
looked at it knows that <tt>complex_tag</tt> is aptly named
indeed…
</p>
<p>
It can do more useful things, however, like generating elements
on the fly, dynamically populating them (e.g. from a database),
and so forth.
</p>
<p>
The <a href="#example">next section</a> of this page is rather
inane and simply shows a few examples of <tt>taglib</tt> in
action. There’s also a <a href="#source">source listing</a>
<em>for</em> this page.
</p>
</entry>
<entry id="my_entry">
<h2 id="#example">Preliminaries</h2>
<p>
Here’s some tag soup, with some non-ASCII characters thrown
in. It may be unsurprising that a guy named ‘Häggholm’
should build a library that focuses strictly on Unicode
strings… We’ll be parsing this stuff into an
object-oriented structure.
</p>
<p style="font-weight: bold;">
This has to be valid XML, except that no root element is
required.
</p>
<p class="small">
Strictly speaking, that means it <em>can’t</em> be real
<q>tag soup</q>.
</p>
</entry>
<entry>
<h2>Fun with sequences</h2>
<p>
Let’s have a list! Note that this is filled with a
<tt>dict</tt>, which is unordered. You may want some kind of
ordered map for this one…
</p>
<ol id="french_list" />
<p>
<em>Obviously</em>, we can make ’em unordered.
</p>
<ul id="item_list" />
</entry>
<entry>
<h2>And of course tables are good, too</h2>
<table id="the_table" class="tabular" />
</entry>
<entry>
<h2 id="source">Source listing</h2>
<textarea id="sourcecode" />
</entry>
"""
ts = self.parse(soup)
ts['my_entry'].content += [
tags.p(u'Here’s a rather differently generated paragraph.'),
tags.p(u'Here’s another one.'),
tags.ul(['And', 'a', 'list'])
]
ts['french_list'].content = {'one': 'Un!', 'two': 'Deux!',
'three': 'Trois!'}
ts['item_list'].content = ['Towel', 'Sub-etha-thingamajig', 'Guide']
# Why the three levels of nesting for a list? Well, a <table> can
# have more than one <tbody>, so the content is an sequence of
# tbodies; each a sequence of rows; each a sequence of cells.
ts['the_table'].caption = 'Just a table caption'
ts['the_table'].head = ['#1', '#2', '#3', '#4']
ts['the_table'].foot = ts.dom['the_table'].head
ts['the_table'].content = [[
['here', 'are', 'some', 'words'],
['sitting', 'in', 'a', 'table'],
['with', 'head', 'and', 'foot']
]]
def fix(l):
return l.replace(u'&', u'&').replace(u'>', u'>').replace(u'<', u'<')
with codecs.open(self.meta.dir+'/taglibdemo.py', 'r', 'utf-8') as f:
ts['sourcecode'].content = u''.join(f.readlines())
# Inline CSS isn't nice, but for now...
self.css = "#sourcecode { width: 100%; height: 40em; }"
return ts