Tclhttpd Content Wrapping

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.?

CMcC it's lower powered - doesn't nest. The wrapper can be a template, and it'll work for a whole directory (or class of files) by virtue of being placed in a /.tml file, and the wrapper name is implicit. Much the same, otherwise.


    # 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