|
From: John S. J. A. <ja...@ge...> - 2000-08-07 04:06:39
|
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Greetings all --
I figured I should drop y'all a line and let you know what's going on
with BOP.
A couple of weeks ago, I decided I didn't care for the way I'd split
functions across the various parts of BOP. One thing lead to another,
and I ended up chucking everything except Bop.pm, and re-writing
everything so that the different kinds of BOP objects are all accessed
via the same API.
Since then, I've been working on finishing up the 'base' release,
defined as something that would allow management of static content
(with the exception of 'blog-style Entry objects). I'm getting close
to that -- sometime this week, I hope to finish up the last little
bits that remain. Once that's done, I'll do the BOP website (just for
practice), and then release a 0.1 version.
After that, I'll be working on getting Entry support to work, and then
embedded Perl. Those will be the 0.2 and 0.3 releases, respectively.
I'd also like to get some user feedback before the 0.1 release; I
realize this may not be possible, because the documentation, umm,
sucks. Pretty hard, too. (Anyone who wanted to volunteer to work on
fixing that would earn my eternal gratitude, by the way.)
In order to kludge around the lack of documentation, I'm going to spew
a bit about the way BOP is designed to work. At some point, this is
going to _become_ the documentation, so feedback here is welcomed to.
BOP is designed to work with pieces of HTML (and eventually) Perl that
are encapsulated into objects. Some attributes of these objects are
accessible and editable by the user, and some are only available to
the inner workings of BOP. BOP objects come in five different flavors:
TEMPLATEs, PAGEs, INCLUDEs, ENTRYs, and GLOSSs.
Before getting into the specifics of each of these types of objects,
let's talk about what they have in common: Each object supports three
basic methods: new(), edit(), and insert(). Generally, these will be
called in exactly that order.
new(), as might be expected, creates and returns a BOP object. You
should call it with a single parameter, a string containing the type
of object you want back. The call will bless() and return the
appropriate object type, like so:
$page = Bop->new( 'PAGE' );
If you call new() with a second string parameter containing the name
of an object that's already in the database, that object will be
retrieved and returned:
$index = Bop->new( 'PAGE' , 'index page' );
Note that the namespaces for the different object types are separate,
so specifying the right object type is important.
The second general method is edit(). This object method allows the
user to use their text editor to modify the values of an object. It
handles both new objects (which are generally lacking data) and
existing objects (which have a copy of information from the
database). It also handles converting to and from internal/external
data formats where needed.
The final general method is insert(). This object method takes the
data present in an object and inserts it into the database. It handles
the differences between new objects (INSERTS into the database) and
existing objects (UPDATES of the database). It also updates the
various internal tables that track which objects contain other objects
and which pages have been changed and need to be re-published (see
below).
Oh -- I forgot -- there's a fourth method: is(). When passed an object
type string, this object method returns true or false, depending on
the type of the calling object. That is:
my $page = Bop->new( 'PAGE' );
$page->is( 'TEMPLATE' );
# false
$page->is( 'PAGE' );
# true
OBJECT EMBEDDING
As alluded to above, objects can contain references to other objects,
which cause the contents of the embedded object to be inserted into
the containing object when the latter is published. Not all objects
can contain other objects. In a special case of embedding, each PAGE
object contains a reference to a TEMPLATE object, but the PAGE content
is inserted into the TEMPLATE at the time of publishing. TEMPLATES and
PAGES can contain INCLUDEs, ENTRYs, and GLOSSs, while INCLUDEs and
ENTRYs can contain INCLUDEs and GLOSSs.
Actually embedding an object is easy: just insert the following bit of
pseudo-HTML into the text part on an object:
<%O:name%>
where 'O' is an object type code, and 'name' is the name of an
object. The object type codes are as follows:
p = page
e = entry
g = gloss
i = include
(Note 1: ENTRY objects don't really work yet. In fact, they don't work
at all -- so it's probably better to leave them alone.)
(Note 2: Embedding a page actually causes a _link_ to that page to be
generated. It's subject to the GLOSS object name remapping described
below. Real Soon Now, proper relative paths will be calculated for the
URLs of intra-page links, but this is currently not being done.)
GLOSS objects can use a special syntax to re-map the anchor string of
the glossary item to something else. For example, if there is a
glossary item named 'genehack' that causes
<A HREF="http://genehack.org">Genehack</A>
to be inserted into the page, using this syntax:
<%g:genehack=John's page%>
will cause this insertion upon publication:
<A HREF="http://genehack.org">John's page</A>
One thing that I'm pretty happy about is that BOP keeps track of which
objects are embedded in which other objects, back up to the PAGE
level, which means that when an INCLUDE is changed, all the PAGEs and
TEMPLATEs that contain that INCLUDE are flagged as changed too --
which means that a later Bop->publish_changed() call will result in
them all being re-output.
PUBLISHING
Once objects have been added to the database, HTML files need to be
generated from those objects and uploaded to a server. The publish()
method allows this to happen. Only PAGE objects support the publish()
method; calling publish() on another object type will result in an
error.
Calling publish() results in a copy of the PAGE object's text
attribute, with all embedded references chased down and inserted, to
be output. The output file is named from a combination of the output
directory and the PAGE object URL attribute (and this too needs to be
a bit more intelligent). Basically, the end result is a local mirror
of the web site, rooted in the output directory.
There are also a couple of class methods (publish_changed() and
publish_all()), but they have yet to be implemented. When they are,
they'll do what you think they will.
SUMMARY
Hopefully that should be enough to get you started playing around with
BOP; for now, the basic cycle should look like:
use Bop;
$object = Bop->new( $OBJECT_TYPE );
$object->edit();
$object->insert();
if( $object->is( 'PAGE' )) {
$object->publish();
}
Of course, soon that conditional and publish() call will be replaced
with a single Bop->publish_changed() call.
OK, I think that's it, for now. If you made it all the way through
this, thanks! Any feedback (positive or negative) is very, very
welcome.
john.
- --
- ----------------------------------------------------------------------------
[ John S Jacobs Anderson ]------><URL:mailto:ja...@ge...>
[ Genehack: Not your daddy's weblog ]------><URL:http://genehack.org>
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.2 (GNU/Linux)
Comment: Mailcrypt 3.5.5 and Gnu Privacy Guard
iD8DBQE5jjXkWRJRdOm3KFARAoEFAKCpD5g95EkgjdTVUH+ETD6MABc+1gCeJuLa
dwif41Xx6H5BGNNwx+HAaZo=
=WYxo
-----END PGP SIGNATURE-----
|