nick - it's dead easy, once you know how... :)
for empty (self-closing) tags -
template_tag tag_name { params } {
do stuff
template::adp_append_string $html
}
in the script body,
$params is an ns_set of the attributes and properties passed to the custom tag. if the value equals the key it's an attribute, otherwise it's a property.
$html is what ends up getting inserted into the page.
tags with content are exactly the same, except for an extra "chunk" parameter that gives you whatever was inside the tag...
template_tag tag_name { chunk params } {
do stuff
template::adp_append_string $html
}