Sometimes it's useful to be able to abstract away structural stuff, like headers, margins, footers and such. The following code can be put in the custom directory, and is suitable as a post-generation filter. What this means is that if you put [[Httpd_Filter [[Httpd_CurrentSocket]] Wrap]] into the .tml of a directory, any template will be substituted into wrapper.html instead of the token ''%BODY%''. It's not perfect: changes in the wrapper won't regenerate the whole page. -- [CMcC] 20041203 ---- [WJR] - Sounds interesting. How does this compare to the use of Doc_Include for inclusion of headers, footers, etc.? ---- # wrap.tcl # # This code will use the post-content filter to substitute content # into a file called wrapper.tml or wrapper.html at the point where %BODY% occurs. # # To trigger this, put the following in a Doc domain's .tml # # Httpd_Filter [Httpd_CurrentSocket] Wrap package require struct::list proc Wrap {sock content} { upvar #0 Httpd$sock data global Template foreach dir [::struct::list::Lreverse [Doc_GetPath $sock]] { set template [file join $dir wrapper$Template(tmlExt)] set wrapper [file join $dir wrapper$Template(htmlExt)] if {[file exists $template] && (![file exists $wrapper] || ([file mtime $template] > [file mtime $wrapper]))} { # instantiate the wrapper set dynamic 0 set wrapper [TemplateInstantiate $sock $template $wrapper $data(suffix) dynamic 0] set content [string map [list %BODY% $content] $wrapper] break } elseif {[file exists $wrapper]} { # the wrapper exists set fd [open $wrapper]; set wrapper [read $fd]; close $fd set content [string map [list %BODY% $content] $wrapper] break } } return $content } ---- '''Revisions''': [20041204]: improved template generation, used variables for extensions ---- [[[Category Tclhttpd]]]