[Background - I'm porting my golang blog app to racket, and figuring it out as I go]
I've been working through the web-server-lib docs and learning to use
include-template. In my existing app, the installation of the blog software is separate from the templates, content, and other assets for a specific site. I did some work to configure the site-base and relative template and posts paths, but found that
include-template will not read the template, but fails with "bad relative pathname string". After some frustrating RTFMing I found that all the variants of
include* in racket expect a
path-spec that is only a relative path:
string refers to a file using a platform-independent relative path
A jump to Github led me to the actual code:
(unless (module-path? s)
"bad relative pathname string"
I didn't read up on
module-path? yet but I assume it keeps to things under the module file system structure.
I can imagine this is a security feature since
include-template derives (not in the technical sense) from the same code that is used for
require, ie trying to avoid a malicious program from
/etc/passwd for example.
This leaves me with the question: is there a way to integrate with
web-server/templates where I read the files myself and add them to some namespace so that they can be included (including in sub-templates) or am I trying to do something 1) bad 2) stupid 3) both?
I really don't want to embed the entire look and feel of a site into the racket application?
After a lot more research realized this was way more complicated than I needed, and I'm looking now at just copying the templates to a "nearby" tmp directory that can be required from (hoping it works)
Keep in mind that, in using
web-server/templates, you're effectively running a program written in
#lang scribble/text, IIRC.
As for the relative paths, probably you need to set
current-load-relative-directory to the directory containing the template. Then use the relative file names in the requires.
Also, to access certain variables within the template -- e.g.
@title and so on, which is kind of the whole point of a template approach -- then you need to:
- create a namespace
- attach/require some other modules into that
- make a form that introduces your own variable bindings and calls
eval that form in that namespace (and with the load-relative directory set).
I found this confusing when I did it many years agoo, for my now-dormant blog app, Frog. I got some help on the old mailing list, and cargo-culted some things. I barely understood how/why it worked, years ago, much less today.
Having said that, you're welcome to scrounge my old code. See template.rkt, which provides a wrapper for
include-template -- a
render-template function. It takes a directory, a template file path, and a dictionary of variables/values to be used within the template. It returns the HTML text. Search other files for some example uses of
Hi Greg! I actually found Frog and have been trolling through the code for a few days! Thanks! I do need to revisit your template code, I didn't understand it at all when I started, but I've been deep in racket's include code recently so hopefully it will make more sense.
Question @greghendershott -- I understand that templates are their own "lang" (scribble/text) but is there a performance hit or something? Your "keep in mind" felt a bit like a "beware"
Not re performance. Just in terms of how to use
include-template. Using the template is effectively like running an end user program, and you need to be aware of things like namespaces and load-directories, which you wouldn't with a "normal" function call. Also the use of
eval, which is usually a smell, is IIUC fine here.